计算属性Computed
定义
当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值
为什么使用计算属性
模板内的放入过多复杂逻辑的东西。会让模板变得复杂,且难于维护。
使用方法
const vm = new Vue({
el:"#app",
data:{
user:{
name:"AAA",
email:"12345"
}
},
computed:{
displayName:{
get(){
const user = this.user
return user.name || user.email
},
set(value){
this.user.name = value
}
}
},
template:`
<div>
{{displayName}}
<button @click="changeName">变</button>
</div>
`,
methods:{
changeName(){
this.user.name = "BBB"
}
}
})
如代码所示,计算属性以对象形式编写,不加括号,可以设置getter和setter
计算属性缓存 vs 方法
计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要数据不发生改变,多次访问计算属性会立即返回之前的计算结果,而不必再次执行函数,节省内存。
简而言之:
- 如果依赖的属性不变化,计算属性就不会重新计算
- getter、setter 默认不做缓存
watch
当 data 的数据发生变化时,执行对应的回调函数,有两个参数,一个 value (修改后的 data 数据),一个 oldValue(原来的 data 数据)
代码示例
new Vue({
data: {
n: 0,
obj: {
a: "a"
}
},
template: `
<div>
<button @click="n += 1">n+1</button>
<button @click="obj.a += 'hi'">obj.a + 'hi'</button>
<button @click="obj = {a:'a'}">obj = 新对象</button>
</div>
`,
watch: {
n() {
console.log("n 变了");
},
obj:{
handler: function (val, oldVal) {
console.log("obj 变了")
},
deep: true // 该属性设定在任何被侦听的对象的 property 改变时都要执行 handler 的回调,不论其被嵌套多深
},
"obj.a":{
handler: function (val, oldVal) {
console.log("obj.a 变了")
},
immediate: true // 该属性设定该回调将会在侦听开始之后被立即调用
}
}
}).$mount("#app");
如何定义变化
参考=== 的计算规则,简单类型看值,复杂类型看地址
语法
-
一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用
$watch(),遍历 watch 对象的每一个 property。 -
示例:
var vm = new Vue({ data: { a: 1, b: 2, c: 3, d: 4, e: { f: { g: 5 } } }, watch: { a: function (val, oldVal) { console.log('new: %s, old: %s', val, oldVal) }, // 方法名 b: 'someMethod', // 该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深 c: { handler: function (val, oldVal) { /* ... */ }, deep: true }, // 该回调将会在侦听开始之后被立即调用 d: { handler: 'someMethod', immediate: true }, // 你可以传入回调数组,它们会被逐一调用 e: [ 'handle1', function handle2 (val, oldVal) { /* ... */ }, { handler: function handle3 (val, oldVal) { /* ... */ }, /* ... */ } ], // watch vm.e.f's value: {g: 5} 'e.f': function (val, oldVal) { /* ... */ } } }) vm.a = 2 // => new: 2, old: 1 -
deep 控制是否要看这个对象里面的属性变化
-
immediate 控制是否在第一次渲染是执行这个函数
-
不应该使用箭头函数来定义 watcher 函数,因为箭头函数没有 this,它的 this 会继承它的父级函数,但是它的父级函数是 window,导致箭头函数的 this 指向 window,而不是 Vue 实例
另一种调用方式
vm.$watch('data属性名', fn, {deep: .., immediate: ..})
总结
- 如果一个数据需要复杂计算并多次调用就使用计算属性
- 如果一个数据的变化需要被监听并且对数据做一些操作就用 watch