computed
- computed 是 计算属性,它会根据所依赖的数据计算新的结果。
- 具备 缓存 功能,会缓存所依赖的属性的值。当缓存所依赖的属性的值发生变化才会重新计算。
- computed 的设计初衷是用于解决 template 模板(
{{}})中声明式逻辑过多造成不便的问题。 Vue的模板内可以写表达式,但在模板中放入太多的逻辑会让模板过重且难以维护。对于任何复杂逻辑,Vue 推荐使用计算属性。
示例一:CodeSandbox
示例二:
var vm = new Vue({
data: { a: 1 },
computed: {
// 仅读取
aDouble: function () {
return this.a * 2
},
// 读取和设置
aPlus: {
get: function () {
return this.a + 1
},
set: function (v) {
this.a = v - 1
}
}
}
})
vm.aPlus // => 2
vm.aPlus = 3
vm.a // => 2
vm.aDouble // => 4
watch
- watch 指 侦听 / 监听,当响应式属性发生变化时会触发一个回调函数,Vue 实例将会在实例化时调用
$watch(),遍历 watch 对象的每一个 property。有两个参数(oldVal 和 newVal) - 注意: 不能使用箭头函数来定义 watcher 函数。
- ( 理由是箭头函数绑定了父级作用域的上下文,所以
this将不会按照期望指向 Vue 实例)
- ( 理由是箭头函数绑定了父级作用域的上下文,所以
示例:CodeSandbox
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: {
handler() {
console.log("n变了");
},
immediate: true,
//immediate:第一次执行函数时是否立刻渲染
},
obj: {
handler() {
console.log("obj变了");
},
deep: true,
//deep可理解为向深层看,true时就是当obj里面的内容变化时,也认为obj变了
//默认是deep: false。也就是自身地址变化才算变。默认可不写,如下:
/*
obj() {
console.log("obj变了");
},
*/
},
"obj.a": function () {
console.log("obj.a变了");
},
},
}).$mount("#app");
watch 的写法
除了上述例子中的写法外,还可以用 vm.$watch()方法写,比如
new Vue({
watch: {
n() {
console.log("n变了");
}
},
})
可以写成
const vm = new Vue({ });
vm.$watch('n',function(){
console.log("n变了");
})
还可以使用生命周期钩子
new Vue({
created() {
this.$watch(
"n",
function () {
console.log("n变了");
}
)
}
})
deep 选项
- 作用是发现对象内部值的变化。
示例:给data添加obj,里面是 a: "a"。添加两个按钮,用watch监听。
new Vue({
data: {
obj: {
a: "a",
},
},
template: `
<div>
<button @click="obj.a+='hi'">obj.a + 'hi'</button>
<button @click="obj={a:'a'}">obj = 新对象</button>
</div>
`,
watch: {
obj() {
console.log("obj变了");
},
},
"obj.a": function () {
console.log("obj.a变了");
},
},
}).$mount("#app");
当我们点击按钮【obj.a + 'hi'】时发现打印了obj.a变了,但是不打印obj变了,按理来说应该都打印。这里看出 Vue 没有发现obj内部值的变化。
原因:Vue 有一个 deep 选项。用来发现对象内部值的变化。但是默认 deep : false.也就是如果对象是嵌套的,不会去监听其内部。可以改成 deep : true,就可以对对象内部进行监听。 如下:
watch: {
obj:{
handler(){
console.log("obj变了");
},
deep: true
},
},
"obj.a": function () {
console.log("obj.a变了");
},
},
immediate
- 在选项参数中指定
immediate: true将立即以表达式的当前值触发回调。也就是回调将会在侦听开始之后被立即调用。
示例:代码执行便会立即打印出n变了
new Vue({
data: {
n: 0,
},
template: `
<div>
<button @click="n +=1">n + 1</button>
</div>
`,
watch: {
n: {
handler() {
console.log("n变了");
},
immediate: true,
//immediate:第一次执行函数时是否立刻渲染
},
}).$mount("#app");
区别
- computed是计算属性,具有缓存功能;watch 是指侦听,没有缓存的功能,每次都需要执行函数。
- 需要产生新数据或简化 template 选择 computed ;需要监听数据变化或想在数据变化时做些操作选择 watch。
- computed 不支持异步操作, watch 支持异步操作。