vue中的watch是一个比较重要的概念,通过他我们可以检测data的变化,下面进行详细的介绍。
watch定义方式如下:
{[key: string]: string | Function | Object }
即在watch中,
- 键是一个字符串,它是被观测的对象。
- 值可以是一个字符串,这个字符串是方法名。
- 值还可以是一个函数,但不能使用箭头函数的形式,this会出现问题。
- 值也可以是一个对象,其中包含回调函数可以其他一些选项:比如是否深度遍历。
简单的监听
- 键是字符串,直接指向观测对象
<body>
<div id="app">
<input type="text" v-model="num">
</div>
<script src="vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
num: ''
},
watch: {
num(newVal, oldVal) {
// 监听 num 属性的数据变化
// 作用 : 只要 num 的值发生变化,这个方法就会被调用
// 第一个参数 : 新值
// 第二个参数 : 旧值,之前的值
console.log('oldVal:',oldVal)
console.log('newVal:',newVal)
}
}
})
</script>
</body>
immediate(立即处理 进入页面就触发)
<body>
<div id="app">
<input type="text" v-model="num">
</div>
<script src="vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
num: 1
},
watch: {
num: {
// 数据发生变化就会调用这个函数
handler(newVal, oldVal) {
console.log('oldVal:', oldVal)
console.log('newVal:', newVal)
},
// 立即处理 进入页面就触发
immediate: true
}
}
})
</script>
</body>
deep(深度监听)
对象和数组都是引用类型,引用类型变量存的是地址,地址没有变,所以不会触发watch。这时我们需要进行深度监听,就需要加上一个属性 deep,值为 true。
<body>
<div id="app">
<input type="button" value="更改名字" @click="change">
</div>
<script src="vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
food: {
id: 1,
name: '冰激凌'
}
},
methods: {
change() {
this.food.name = '棒棒糖'
}
},
watch: {
// 第一种方式:监听整个对象,每个属性值的变化都会执行handler
// 注意:属性值发生变化后,handler执行后获取的 newVal 值和 oldVal 值是一样的
food: {
// 每个属性值发生变化就会调用这个函数
handler(newVal, oldVal) {
console.log('oldVal:', oldVal)
console.log('newVal:', newVal)
},
// 立即处理 进入页面就触发
immediate: true,
// 深度监听 属性的变化
deep: true
},
// 第二种方式:监听对象的某个属性,被监听的属性值发生变化就会执行函数
// 函数执行后,获取的 newVal 值和 oldVal 值不一样
'food.name'(newVal, oldVal) {
console.log('oldVal:', oldVal) // 冰激凌
console.log('newVal:', newVal) // 棒棒糖
}
}
})
</script>
</body>
Watch和computed的区别
Watch
watch用于观察和监听页面上的vue实例,当你需要在数据变化响应时,执行异步操作,或高性能消耗的操作,那么watch为最佳选择
computed
可以关联多个实时计算的对象,当这些对象中的其中一个改变时都会触发这个属性
具有缓存能力,所以只有当数据再次改变时才会重新渲染,否则就会直接拿取缓存中的数据。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
</head>
<body>
<script>
var vm = new Vue({
data: {
a: 1,
b: 2,
c: {
name: "JohnZhu"
}
},
watch: {
//值是函数
a: function (val, oldVal) {
console.log('new a: %s, old a: %s', val, oldVal)
},
//值是方法名
b: 'someMethod',
// 深度 watcher,检测到变化,并打印出c.name变化前后的结果
'c.name': {
handler: function (val, oldVal) {
console.log('new c: %s, old c: %s', val, oldVal);
},
deep: true
},
// 报错 必须用c.name,否则在data下不能直接找到name
// name: function () {
// console.log('new c: %s, old c: %s', val, oldVal);
// }
// 报错,键值必须是一个字符串,所以用引号括起来
// c.name: {
// handler: function (val, oldVal) {
// console.log('new c: %s, old c: %s', val, oldVal);
// },
// deep: true
// }
// 这里未检测到变化
// c : {
// handler: function (val, oldVal) {
// console.log('new c: %s, old c: %s', val, oldVal);
// },
// deep: false
// },
// 成功检测到变化
c : {
handler: function (val, oldVal) {
console.log('new c: %s, old c: %s', val, oldVal);
},
deep: true
},
// 检测不到变化,因为参数 deep 的默认值是false
// c : {
// handler: function (val, oldVal) {
// console.log('new c: %s, old c: %s', val, oldVal);
// },
// },
},
methods: {
someMethod: function () {
alert("b is changed");
}
}
})
vm.a = 2; // new: 2, old: 1
vm.b = 666; // alert 666
vm.c.name = "HTT";
</script>
</body>
</html>
总结:
- watch函数的参数中,第一个是改变之前的值,第二个是改变之后的值, 这两个参数非常有用。
- 这里分别使用了 三种定义函数(或option)的方法。
- 如果要观察data下一个对象的属性,我们可以使用 '对象.属性' 的方式, 注意: 一定要要引号。
- 如果改变了一个对象的属性,就必须使用 deep: true, 否则检测不到变化。