vue学习(四)computed
一、为什么要使用computed?
我们都知道,在模板内的表达式非常遍历的,但是有时候,我们会在模板内的放入太多逻辑的东西。会让模板变重,且难于维护。
<div id="example"> {{ message.split('').reverse().join('') }} </div>
在这模板中的代码中,其实,我们需要花费上一小段时间去理解,这块渲染的是message的翻转字符串。然而,当初模板中使用表达式的初衷时为了简单运算的。所以从这点出发,我们就不建议在模板中使用过于复杂的表达式了。此时,计算属性就横空出世了。计算属性就是当依赖的属性的值发生变化的时候,才会触发他的更改,如果依赖的值,不发生变化的时候,使用的是缓存中的属性值。
定义:当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值。
<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('') } } })
计算属性允许我们对指定的视图,复杂的值计算。这些值将绑定到依赖项值,只在需要时更新。
例如,我们可以在数据模型中有一个results数组:
假设想要查看所有主题的总数。我们不能使用filters或expressions来完成这个任务。
- filters:用于简单的数据格式,在应用程序的多个位置都需要它
- expressions:不允许使用流操作或其他复杂的逻辑。他们应该保持简单
这个时候,计算属性就可以派上用场。我们可以向模型中添加一个计算值,如下:
效果如下:
当然也可以使用Vue中的method计算出学科的总分,最终得到的总数结果是相同的。
在上例的基础上,我们把computed区块中的totalMarks函数整体移到methods中。同时在模板中将{{ totalMarks }} 替换成{{ totalMarks() }}。 最终看到的结果是一样的,如下所示:
虽然这两种方式输出的结果是相同的,但是用method方法的性能将遭受毁灭性的打击。使用这种方法totalMarks()方法在每次页面渲染时都被执行一次(例如,使用每一个change)。
如果我们有一个计算属性,那么Vue会记住计算的属性所依赖的值(在我们这个示例中,那就是results)。通过这样做,Vue只有在依赖变化时才可以计算值。否则,将返回以前缓存的值。这也意味着只要results还没有发生改变,多次访问totalMark计算属性会立即返回之前的计算结果,而不必再次执行函数。
上面两个示例也说明,在Vue中计算属性是基于它们的依赖进行缓存的,而方法是不会基于它们的依赖进行缓存的。从而使用计算属性要比方法性能更好。
二、getter函数
getter和setter函数参考文章https://www.jianshu.com/p/56f337688d6b
在 Vue 中,computed 的属性可以被视为是 data 一样,可以读取和设值,因此在 computed 中可以分成 getter(读取) 和 setter(设值),一般情况下是没有 setter 的,computed 预设只有 getter ,也就是只能读取,不能改变设值。
vue.js计算属性默认只有 getter,因为是默认值所以我们也常常省略不写,如下代码:
<div id="demo">{{ fullName }}</div> var vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar' }, computed: { fullName: function () { return this.firstName + ' ' + this.lastName } } })
其实computed里的代码完整的写法应该是:
computed: { fullName: { get(){ return this.firstName + ' ' + this.lastName } } }
需要注意的是,不是说我们更改了getter里使用的变量,就会触发computed的更新,前提是computed里的值必须要在模板里使用才行。
三、setter函数
当赋值给计算属性的时候,将调用setter函数。多用于在模板组件中需要修改计算属性自身的值的时候。
computed: { updateMessage: { get: function() { console.log('计算属性', this.message) return this.message }, set: function(newVal) { this.message = newVal console.log('newVal', newVal) } } }, mounted () { this.updateMessage = '222' console.log('测试:', this) },
只有当计算属性中的属性被直接赋值的时候,才会走setter函数,而且,setter函数和getter函数是相互独立的,不是说走setter函数,就必须走getter函数。上面的案例,打印结果是
newVal: 222,
计算属性: 222
是因为,在setter中触发了message的更改,当message发生改变的时候,getter函数中就会改变。执行顺序是setter -> getter -> updated
computed: { updateMessage: { get: function() { console.log('计算属性', this.message) return this.message }, set: function(newVal) { console.log('newVal', newVal) } } }, mounted () { console.log('测试:', this) },
这种情况下,打印结果是:
newVal 222
此时,就只是单单的走了setter的函数,而没有走getter函数。