vue计算属性和监听器实例解析


Posted in Javascript onMay 10, 2018

基本实例

<div id="example">
 <p>Original message: "{{ message }}"</p>
 <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
 el: '#example',
 data: {
  message: 'Hello'
 },
 computed: {
  // 计算属性的 getter
  reversedMessage: function () {
   // `this` 指向 vm 实例
   return this.message.split('').reverse().join('')
  }
 }
})

结果:

Original message: "Hello"
Computed reversed message: "olleH"

这里我们声明了一个计算属性 reversedMessage。我们提供的函数将用作属性 vm.reversedMessage 的 getter 函数:

console.log(vm.reversedMessage) // => 'olleH'
vm.message = 'Goodbye'
console.log(vm.reversedMessage) // => 'eybdooG'

你可以打开浏览器的控制台,自行修改例子中的 vm。vm.reversedMessage 的值始终取决于 vm.message 的值。

你可以像绑定普通属性一样在模板中绑定计算属性。Vue 知道 vm.reversedMessage 依赖于 vm.message,因此当 vm.message 发生改变时,所有依赖 vm.reversedMessage 的绑定也会更新。而且最妙的是我们已经以声明的方式创建了这种依赖关系:计算属性的 getter 函数是没有副作用 (side effect) 的,这使它更易于测试和理解

计算属性缓存 vs 方法

你可能已经注意到我们可以通过在表达式中调用方法来达到同样的效果:

<p>Reversed message: "{{ reversedMessage() }}"</p>
// 在组件中
methods: {
 reversedMessage: function () {
  return this.message.split('').reverse().join('')
 }
}

我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。

这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:

computed: {
 now: function () {
  return Date.now()
 }
}

相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。

我们为什么需要缓存?假设我们有一个性能开销比较大的的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。

计算属性 vs 侦听属性

Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch——特别是如果你之前使用过 AngularJS。然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。细想一下这个例子:

<div id="demo">{{ fullName }}</div>
var vm = new Vue({
 el: '#demo',
 data: {
  firstName: 'Foo',
  lastName: 'Bar',
  fullName: 'Foo Bar'
 },
 watch: {
  firstName: function (val) {
   this.fullName = val + ' ' + this.lastName
  },
  lastName: function (val) {
   this.fullName = this.firstName + ' ' + val
  }
 }
})

上面代码是命令式且重复的。将它与计算属性的版本进行比较:

var vm = new Vue({
 el: '#demo',
 data: {
  firstName: 'Foo',
  lastName: 'Bar'
 },
 computed: {
  fullName: function () {
   return this.firstName + ' ' + this.lastName
  }
 }
})

好得多了,不是吗?

计算属性的 setter

计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter :

// ...
computed: {
 fullName: {
  // getter
  get: function () {
   return this.firstName + ' ' + this.lastName
  },
  // setter
  set: function (newValue) {
   var names = newValue.split(' ')
   this.firstName = names[0]
   this.lastName = names[names.length - 1]
  }
 }
}
// ...

现在再运行 vm.fullName = 'John Doe' 时,setter 会被调用,vm.firstName 和 vm.lastName 也会相应地被更新。

侦听器

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

例如:

<div id="watch-example">
 <p>
  Ask a yes/no question:
  <input v-model="question">
 </p>
 <p>{{ answer }}</p>
</div>
<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 -->
<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
 el: '#watch-example',
 data: {
  question: '',
  answer: 'I cannot give you an answer until you ask a question!'
 },
 watch: {
  // 如果 `question` 发生改变,这个函数就会运行
  question: function (newQuestion, oldQuestion) {
   this.answer = 'Waiting for you to stop typing...'
   this.getAnswer()
  }
 },
 methods: {
  // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
  // 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
  // AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
  // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
  // 请参考:https://lodash.com/docs#debounce
  getAnswer: _.debounce(
   function () {
    if (this.question.indexOf('?') === -1) {
     this.answer = 'Questions usually contain a question mark. ;-)'
     return
    }
    this.answer = 'Thinking...'
    var vm = this
    axios.get('https://yesno.wtf/api')
     .then(function (response) {
      vm.answer = _.capitalize(response.data.answer)
     })
     .catch(function (error) {
      vm.answer = 'Error! Could not reach the API. ' + error
     })
   },
   // 这是我们为判定用户停止输入等待的毫秒数
   500
  )
 }
})
</script>

结果:

Ask a yes/no question:

I cannot give you an answer until you ask a question!

在这个示例中,使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

除了 watch 选项之外,您还可以使用命令式的 vm.$watch API。

总结

以上所述是小编给大家介绍的vue计算属性和监听器,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JS模块与命名空间的介绍
Mar 22 Javascript
拖动table标题实现改变td的大小(css+js代码)
Apr 16 Javascript
JavaScript 模拟类机制及私有变量的方法及思路
Jul 10 Javascript
JQuery实现点击div以外的位置隐藏该div窗口
Sep 13 Javascript
Javascript浅谈之this
Dec 17 Javascript
js实现仿qq消息的弹出窗效果
Jan 06 Javascript
jQuery实现拖拽页面元素并将其保存到cookie的方法
Jun 12 Javascript
Angular和百度地图的结合实例代码
Oct 19 Javascript
常用的几个JQuery代码片段
Mar 13 Javascript
浅谈Node.js之异步流控制
Oct 25 Javascript
vue.js实现备忘录demo
Jun 26 Javascript
vue同个按钮控制展开和折叠同个事件操作
Jul 29 Javascript
js正则相关知识点专题
May 10 #Javascript
详解node Async/Await 更好的异步编程解决方案
May 10 #Javascript
Javascript Promise用法详解
May 10 #Javascript
jQuery实现模糊查询的方法分析
May 10 #jQuery
async/await地狱该如何避免详解
May 10 #Javascript
Angular4.x通过路由守卫进行路由重定向实现根据条件跳转到相应的页面(推荐)
May 10 #Javascript
JS中的JSON对象的定义和取值实现代码
May 09 #Javascript
You might like
动漫女神老婆无限好,但日本女生可能就不是这么一回事了!
2020/03/04 日漫
动画 《Pokemon Sword·Shield》系列WEB动画《薄明之翼》第2话声优阵容公开!
2020/03/06 日漫
php自动加载机制的深入分析
2013/06/08 PHP
带你了解PHP7 性能翻倍的关键
2015/11/19 PHP
PHP简单字符串过滤方法示例
2016/09/04 PHP
PHP递归的三种常用方式
2019/02/28 PHP
TP5框架使用QueryList采集框架爬小说操作示例
2020/03/26 PHP
JS实现多物体缓冲运动实例代码
2013/11/29 Javascript
jQuery之字体大小的设置方法
2014/02/27 Javascript
jquery实现表格本地排序的方法
2015/03/11 Javascript
jQuery事件的绑定、触发、及监听方法简单说明
2016/05/10 Javascript
jquery配合.NET实现点击指定绑定数据并且能够一键下载
2016/10/28 Javascript
jquery封装插件时匿名函数形参和实参的写法解释
2017/02/14 Javascript
Angular中ng-bind和ng-model的区别实例详解
2017/04/10 Javascript
用js屏蔽被http劫持的浮动广告实现方法
2017/08/10 Javascript
vue-router 权限控制的示例代码
2017/09/21 Javascript
jQuery实现获取form表单内容及绑定数据到form表单操作分析
2018/07/03 jQuery
JS内置对象和Math对象知识点详解
2020/04/03 Javascript
JavaScript数组排序的六种常见算法总结
2020/08/18 Javascript
[49:20]VG vs TNC Supermajor小组赛B组败者组决赛 BO3 第二场 6.2
2018/06/03 DOTA
python访问纯真IP数据库的代码
2011/05/19 Python
Pyhton中防止SQL注入的方法
2015/02/05 Python
Java编程迭代地删除文件夹及其下的所有文件实例
2018/02/10 Python
Pyqt清空某一个QTreeewidgetItem下的所有分支方法
2019/06/17 Python
Django 博客实现简单的全文搜索的示例代码
2020/02/17 Python
解决python3中os.popen()出错的问题
2020/11/19 Python
使用Python爬取Json数据的示例代码
2020/12/07 Python
html5 CSS过度-webkit-transition使用介绍
2013/07/02 HTML / CSS
屈臣氏俄罗斯在线商店:Watsons俄罗斯
2020/08/03 全球购物
Jowissa官方网站:瑞士制造的手表,优雅简约的设计
2020/07/29 全球购物
this关键字的含义
2015/04/08 面试题
高三自我鉴定怎么写
2013/10/19 职场文书
80后职场人的职业生涯规划
2014/03/08 职场文书
村主任“四风”问题个人对照检查材料思想汇报
2014/10/02 职场文书
领导欢送会主持词
2015/07/06 职场文书
追悼会答谢词范文
2015/09/29 职场文书