数据改变(vue视图上的数据能渲染成功)时会触发对应的监听器watch。
vue提供了watch方法,用于监听实例内data数据的变化。
一、普通类型字符串等监听
直接监听
1 | <template> |
二、对于对象
1 | <template> |
监听对象本身
直接监听对象是监听对象的指向,不能监听到某个对象里面属性的变化。
如果需要监听的数据是对象内的某一属性值的变化,直接watch对象friend是检测不到变化的,这是因为friend这个对象的指向并没有发生改变。
1 | <script> |
触发监听
直接改变对象会触发监听
1 | this.friend = { |
监听对象内属性变化
方法一:深度检测
deep设为了true,修改了这个friend中的任何一个属性,都会执行handler这个方法。不过这样会造成更多的性能开销,尤其是对象里面属性过多,结构嵌套过深的时候。而且有时候我们就只想关心这个对象中的某个特定属性。
1 | <script> |
扩展:handler声明函数或函数表达式都可以,但是不能箭头函数
1 | watch : { |
immediate属性
没有的时候上面的例子是值变化时候,watch才执行,我们想让值最初时候watch就执行就用到了handler和immediate属性,immediate : true代表在wacth里声明了newA这个方法之后立即先去执行handler方法,如果设置了false,那么效果和没有一样
方法二:字符串来表示属性的调用
1 | <script> |
方法三:使用computed属性
1 | <script> |
触发监听
1、修改现有对象某个属性对应的值
把对象某个属性的值修改都触发,无论改成基本类型还是引用对象,而且引用对象内vue也能监听到。
1 | // 例1:数据修改成功,视图修改成功=三种方式的属性监听都触发 |
2、属性的添加
对于已经创建的实例,Vue 不允许动态添加根级别(外层内层都监听不到)的响应式 property: 无法渲染
解决方案:
预先留出变量
使用this.$set / Vue.set()
1
2this.friend.sex = "girl"; // 数据修改但无法渲染 = 监听不到
this.$set(this.friend, "sex", "boy"); // 可以渲染,deep watch可以监听3、属性的删除
Vue 无法检测 property 的移除
解决方案:Vue.delete()删除对象某个元素后,会立即触发页面渲染:Vue.delete(propertyName/index)
1
2delete this.friend.age; //数据删除但无法渲染 = 监听不到
this.$delete(this.friend, "age"); // 可以渲染,deep watch可以监听三、对于数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<template>
<div class="about">
<input type="text" :value="colors" />
<input type="text" :value="colors[0]" />
<button @click="changeColors">更新视图</button>
</div>
</template>
<script>
export default {
data() {
return {
colors: ["red", "orange", "green"]
};
},
}
</script>监听数组
1
2
3
4
5
6
7
8
9<script>
export default {
watch: {
colors(newVal, oldVal) {
console.log("colors:newVal--" + newVal + ",oldVal--" + oldVal);
},
},
}
</script>触发监听
1、直接赋值新数组
1
2// 例子1:修改成功,数组、元素都渲染成功,触发上面对数组的监听
this.colors = ["1", "2", "3"];2、利用索引直接设置一个数组项
例如:arr[indexOfItem] = newValue;
解决方案:使用this.$set(arr, index, newVal)
使用splice(indexOfItem, 1, newValue):
使用临时变量直接赋值的方式,原理与直接赋值数组一样
1
2
3
4
5
6
7
8
9this.colors[0] = "blue"; // 不是响应的,数据修改成功但渲染不成功 = 不触发监听
// 方法一:
this.$set(this.colors, 0, "blue") // 渲染成功 = 触发监听
// 方法二
this.colors.splice(0, 1, "blue"); // 渲染成功 = 触发监听
// 方法三
let temp = [...this.colors];
temp[0] = "blue";
this.colors = temp; //渲染成功 = 触发监听3、push数组
Vue可以监听
1
this.colors.push('yellow') // 数据添加成功,视图渲染成功
4、修改数组的长度
例如:arr.length = newLength
长度大于原数组就将后续元素设置为 undefined, 长度小于原数组就将多余元素截掉。
解决方案:this.$set(arr, index, newVal);
使用数组 splice 方法可以监听
使用临时变量直接赋值的方式,原理与直接赋值数组一样
1
2
3this.colors.length = 1; // 数据修改成功,视图渲染不成功
方法一:
this.colors.splice(1) // 渲染成功 = 触发监听 1之后数组的元素都被删除,包括1
