vue watch监听
// ▆ 应用场景:
// ▆1.监听路由,如同一个路由,query传参不同,页面显示不同
watch: {
$route: {
handler(val) {
//如果title=='添加单位代表',清空form表单
if (val.query.title == '添加单位代表') {
//初始化表单
this.ruleForm = this.$options.data().ruleForm
}
//如果title=='编辑单位代表',请求接口
if (val.query.title == '编辑单位代表') {
findOrgRepresentationInfoByIdApi({
id: val.query.id,
}).then((res) => {
this.ruleForm = res.data
})
}
},
deep: true,
immediate: true,
},
},
//▆2.监听省的变化,得到城市
watch: {
'ruleForm.province': function () {
this.ruleForm.city = '' //监听省的变化,清空城市的值
this.countyList = [] //监听省的变化,清空区的数组,如果只清空值,前一个数组还在
findCityApi({ id: this.ruleForm.province }).then((res) => {
this.cityList = res.data
})
},
'ruleForm.city': function () {
this.ruleForm.county = ''//监听市的变化,清空区的值
findCityApi({ id: this.ruleForm.city }).then((res) => {
this.countyList = res.data
})
},
},
//▆3.监听pageNum的变化,当pageNum发生变化,请求一次( ▆点击上下一题提交一次,比较新值和旧值大小,如果新值大于旧值,为空,填写答案;如果新值小于旧值,为请求对象
watch: {
pageNum: function (newVal, oldVal) {
findSubjectByIdApi({
questionId: this.questionId,
pageNum: this.pageNum,
mainAnswerId: this.mainAnswerId,
}).then((res) => {
...
this.fileList = newVal > oldVal ? [] : formatList
})
},
},
// ▆ 一个子组件要改变父组件的data值,并且需要把这个值传给其他兄弟组件,这时候发现其他兄弟组件的data值没有变换还是最初父组件传的值,这时候就用到watch来进行监听了化。
// ▆ ▆用法:数据变化时,来响应对应的数据,比较新值与旧值! 当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
//观察vue实例上的一个表达式或者一个函数计算结果的变化。回调函数得到的参数为新值和旧值。表达式只接受简单的键路径。对于更复杂的表达式,用一个函数取代。
//Watch对象中的回调函数不应该用箭头函数进行定义,它将导致上下文的混乱,this将指向错误的上下文
watch {
{ [key: string]: string | Function | Object | Array }
}
vm.$watch('a.b.c',function(newVal,oldVal){
//做点什么
})
watch:{
// ▆ 1.Function
a:function(val,olaVal){}
// ▆ 2.sting 方法名
b:'someMethod'
// ▆ 3.Object 该回调在任何被侦听的对象的property改变时被调用,不论其被嵌套多深
c:{
handler:function(val,oldVal){}
deep:true
}
//该回调将会在侦听开始之后被立即调佣
d:{
handler:'someMethod'
immediate:true
}
// ▆ 4.你可以传入回调数组,它们会被逐一调用
e: [
'handle1',
function handle2 (val, oldVal) { /* ... */ },
{
handler: function handle3 (val, oldVal) { /* ... */ },
/* ... */
}
]
// ▆ 5.e:{f:1,g:2}
'e.f': function (val, oldVal) { /* ... */ }
}
//▆1.最直接的,直接用方法作为回调函数(或者说作为值)。
<div>
<p>{{msg}}</p>
<input v-model="msg">
</div>
// pattern1 directly method value
watch {
// msg1 为表达式, function(oldVal, newVal)为匿名函数,作为回调函数
msg1: function (newVal, oldVal) {
console.log("oldVal is: " + oldVal + " newVal is: " + newVal);
}
}
//打印有变化 oldVal is: init newVal is: init1 注意,回调函数的第一个参数是新的值,第二个是旧的值。
//▆2.函数名作为值
<div>
<p>{{msg2}}</p>
<input v-model="msg2">
</div>
watch {
msg2: "methodway"
}
methods: {
methodway (newVal, oldVal) {
console.log("oldVal is: " + oldVal + " newVal is: " + newVal);
}
}
//打印有变化 oldVal is: init newVal is: init1
// ▆ 3.观察键为对象/数组时,需要追加选项deep
//注意:在变更(不是替换)对象或者数组,旧值将与新值相同,因为他们的应用指向同一个对象/数组。vue不会保留变更之前值的副本
//当我们的被观察者是一个对象/数组的时候,我们改变了对象内部属性的值,用通常的watch方式是捕捉不到的。因为对于数组、对象本身来说,它并没有改变。这个时候需要加上选项deep: true
<div>
<p>{{msg3.attr1}}</p>
<input v-model="msg3.attr1">
</div>
//如果使用通常方式,改变了msg3的attr1属性值,watch并不会响应。需要加上deep选项:
watch {
msg3: {
handler: function (newVal, oldVal) {
console.log("oldVal is: " + oldVal + " newVal is: " + newVal);
},
// 加上这个选项之后,不论被嵌套得多深,被观察的对象的property一旦改变都会响应
deep:true
}
}
// ▆ 但是在这里的一个输出会有一个问题,虽然你能捕捉到对象的变更,但是你会发现oldVal和newVal是一样的,
// ▆ 打印无变化
//oldVal is: {"attr1":"123","attr2":"2"}
//newVal is: {"attr1":"123","attr2":"2"}
// ▆ 也就是说,虽然我们能捕捉到变化,但是从watch对象里面的回调来说,我们无法准确抓取到变化的属性。如果想做到这点,我们可以单独观察对象的某个属性msg3.attr1或者使用computed做中间层来观察,如下
watch {
'msg3.attr1':
function(newVal, oldVal) {
console.log("oldVal is: " + oldVal + " newVal is: " + newVal);
}
}
// ▆ 4.实例化后立刻回调
// ▆ 有时候会有要求Vue对象实例化后,立刻回调某一个Watch对象的键值。这个时候只需要加上一个选项immediate: true即可
<div>
<p>{{msg4}}</p>
<input v-model="msg4">
</div>
watch {
msg4: {
handler(newVal, oldVal) {
console.log("this should be called immediately.");
},
//比如当父组件向子组件动态传值时,子组件props首次获取到父组件传来的默认值时,也需要执行函数,此时就需要将immediate设为true。
// 加上immediate选项后,实例化后立刻回调一次
immediate:true
},
}
console输出:// 注意,我们并没有改变input的值,实例化之后立刻进行了回调
this should be called immediately.