前言
上次接触watch还是面试的时候,由于第一次学Vue蜻蜓点水加搁置时间很久了,所以只知道watch是监听状态的。今天这篇文章,用于详细的记录Vue中的watch监视属性。
题外话
阻止Vue在启动时生成生产提示 Vue.config.productionTip=false
代码案例1-基于侦听属性的天气案例
<!-- 天气案例 -->
<div id="weather">
<h2>今天的天气情况:{{info}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
<script>
const vm = new Vue({
el: '#weather',
data: {
isHot: true
},
computed: {
info() {
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot
}
},
watch: {
info: {
immediate: true,
handler(newValue, oldValue) {
console.log('info被修改', newValue, oldValue)
}
}
}
})
</script>
代码解析
天气的切换是因为切换isHot的值,watch的值是配置对象 在watch下面监视isHot,当值发生变化控制台输出提醒。
watch: {
isHot: {
immediate: true,
handler(newValue, oldValue) {
console.log('isHot被修改', newValue, oldValue)
}
}
}
handler当isHot发生改变时调用,immediate:true可以实现初始化时让handler调用一下,注意immediate是写在handler的前面,否则不生效。 watch不仅可以监视isHot,也可以监视info,如代码案例1
第一次监测info第二个值undefined是因为还未发生改变,单击切换天气后数据发生改变,第二个值不再是undefined。
如果不写watch,也可以在创建实例后在实例外面写
vm$watch('isHot',{
immediate:true,
handler:(newValue,oldValue){
console.log('isHot被改',newValue,oldValue)
}
})
如果明确知道监视谁就写watch,如果写完了想到要用watch可以用下面直接调取API的方式。
代码案例2-基于深度侦听的天气案例
深度监视
(1).Vue中的watch默认不监测对象内部值的变化(一层),Vue自身可以监测对象内部值的变化 (2).配置deep:true可以监测对象内部值改变(多层) (3).使用watch时根据数据的具体结构,决定是否采用深度监视,
深度侦听需要遍历被侦听对象中的所有嵌套的属性,当用于大型数据结构时,开销很大。因此请只在必要时才使用它,并且要留意性能。 ------Vue官方文档
<div id="weather">
<h2>今天的天气情况:{{info}}</h2>
<button @click="changeWeather">切换天气</button>
<hr />
<h3>a:{{numbers.a}}</h3>
<button @click="numbers.a++">a+1</button>
<h3>a:{{numbers.b}}</h3>
<button @click="numbers.b++">b+1</button>
<button @click="numbers={a:666,b:888}">彻底替换numbers</button>
numbers.a.b.c.d.e
</div>
<script>
const vm = new Vue({
el: '#weather',
data: {
isHot: true
},
numbers: {
a: 1,
b: 1,
c: {
d: {
e: 100
}
}
},
computed: {
info() {
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot
}
},
watch: {
inHot: {
immediate: true,
deep: true,
handler(newValue, oldValue) {
console.log('inHot被修改', newValue, oldValue)
}
}
}
})
</script>
watch可以简写成如下
vm.$watch('isHot', {
immediate: true,
deep: true,
handler(newValue, oldValue) {
console.log('inHot被修改', newValue, oldValue)
}
})
computed和watch的对比-姓名案例
watch侦听属性实现
<div id="name">
姓:<input type="text" v-model="firstName"><br /><br />
名:<input type="text" v-model="lastName"><br /><br />
姓名:<span>{{fullName}}</span>
</div>
<script>
const vm = new Vue({
el: '#name',
data: {
firstName: '张',
lastName: '三',
fullName: '张-三'
},
watch: {
firstName(newValue) {
console.log(this);
this.fullName = newValue + '-' + this.lastName
},
lastName(val) {
this.fullName = val + '-' + this.firstName
}
}
})
</script>
computed完整实现姓名案例
<div id="name">
姓:<input type="text" v-model="firstName"><br /><br />
名:<input type="text" v-model="lastName"><br /><br />
测试:<input type="text" v-model="x"><br /><br />
姓名:<span>{{fullName}}</span>
<!-- <button @click="demo">点我</button> -->
</div>
<script>
const vm = new Vue({
el: '#name',
data: {
firstName: '张',
lastName: '三',
x: 'hello'
},
computed: {
fullName: {
get() {
console.log('get被调用了')
console.log(this)
return this.firstName + this.lastName
},
set(value) {
console.log('set', value)
const arr = value.split('_')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
</script>
计算属性computed的简写
fullName(){
console.log('get被调用')
return this.firstName+'-'+this.latName
}
姓名案例新的需求:姓发生改变全名延迟5秒显示。 方法:在姓的方法中添加settimeout
firstName(val) { setTimeout(() => { this.fullName = val + '-' + this.lastName }, 5000); },
在watch里面可以开启异步任务,但是计算属性不行,在computed加setTimeout会报错 如图所示
控制台没有报错信息,但全名显示不出来,原因是因为return的值是箭头函数的,fullName没有返回值了(undefined)。如图,fullName的返回值应该是在下面的新的return语句,计算属性不可开启异步任务来维护数据,watch可以,watch根据自己写的代码进行。
定时器写成箭头函数
定时器的回调箭头函数不是普通函数,定时器指定的函数不是Vue所管理的函数,定时器在fullname中开启的,如果写普通函数,this是window,定时器指定的回调时js引擎帮忙会回调的,箭头函数没有自己的this就往外找,就是firstName的this(vm)
computed和watch的区别
1.computed能完成的功能,watch都可以完成 2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。 两个重要的小原则: 1.所有Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象 2.所有不被Vue管理的函数(定时器的回调函数,ajax的回调函数,Promise的回调函数)最好写出箭头函数,这样this的指向才是vm或组件实例对象。
感觉this指向这个知识点也很重要要再去复习一下哈哈哈
要想清楚Vue里面的this首先要明白JavaScript里面this指向的问题。
JavaScript中的this指向问题
window.color = 'yellow';
let a = {
color: 'black'
};
function expressColor() {
console.log(this.color)
}
expressColor();
a.expressColor = expressColor;
a.expressColor();//
运行结果是yellow,black。 分析一下,在全局上下文中调用expressColor(),this指向window,this.color相当于window.color,所以输出是yellow。 而把expressColor()赋值给a之后再调用a.expressColor,this会指向a,this.color相当于a.color,输出black。