参考:
Vue3中watch监视reactive定义数据的“坑” – csdn
watch – Vue.js
vue中watch的使用写法 – csdn
【Vue】watch的详细⽤法 – csdn
vue中watch的用法 – 博客园
前言
在项目中,我想用store来全局管理document.body.clientWidth
然而却发现watch无法监听store中的clientWidth
测试复现
我定义的store是这样的:
const store = {
debug: true,
// 使用一个 reactive 方法让对象作为响应式对象。
bodyWidth: reactive({
value: 0,
}),
setBodyWidthAction(newVal) {
if (this.debug) {
console.log('setBodyWidthAction triggered with', newVal)
}
this.bodyWidth.value = newVal
},
}
加一个按钮去测试:
<el-button @click="testWatch">testWatch</el-button>
data() {
return {
sharedBodyWidth: this.$store.bodyWidth,
}
},
methods: {
testWatch() {
this.$store.setBodyWidthAction(Math.random())
console.log(this.sharedBodyWidth)
},
},
watch: {
sharedBodyWidth: {
handler(newVal) {
console.log(`watch sharedBodyWidth=${newVal.value}`)
},
immediate: true,
},
},
发现了如下打印:
显然我们的set方法执行了,data里的变量也跟随响应式变量bodyWidth改变了
但却没有被watch监听到。
面向百度编程
面向百度编程了半小时,给watch加上了deep参数
普通的watch方法无法监听到对象内部属性的改变,需要deep属性对象进行深度监听。
watch: {
sharedBodyWidth: {
handler(newVal) {
console.log(`watch sharedBodyWidth=${newVal.value}`)
},
immediate: true,
deep: true,
},
},
这下可以了:
扩展
还有另外一种方式也可以实现,直接监听reactive变量的一个属性:
watch: {
'sharedBodyWidth.value': {
handler(newVal) {
console.log(`watch sharedBodyWidth=${newVal}`)
},
immediate: true,
},
},
在我们监听reactive定义的对象时,默认强制开启deep,这也是监听sharedBodyWidth.value
生效的原因。此外oldValue无法监听到。
如果我们要监听reactive对象定义的对象属性的子属性,需手动配置deep: true
。同样的,oldValue无法监听到。
此外,immediate表示在watch中首次绑定得时候,是否执行handler。默认是false
watch的写法
关于watch的写法,大概有4种:
watch: {
// 1: a可以是data,也可以是computed
a(newVal, oldVal) {},
// 2:
a: {
handler(newVal,oldVal){},
immediate:false,
deep:false,
},
// 3:
'a.v': {
handler(newVal,oldVal){},
immediate:false,
deep:false,
},
// 4: 监听store中的状态
'$store.a.value': {
handler(newVal,oldVal){},
}
}
使用store的状态做双向数据绑定
const store = {
inputVal: reactive({
value: "inputVal is a string"
}),
setInputValAction(newValue) {
this.inputVal.value = newValue
},
}
<el-input v-model="inputVal"></el-input>
// ...
computed: {
inputVal: {
get() { // 使用箭头函数this是undefined
return this.$store.inputVal.value
},
set(val) {
this.$store.setInputValAction(val)
},
}
},
watch: {
"$store.inputVal.value": {
handler(newVal) {
console.log(`watch $store.inputVal.value=${newVal}`)
},
immediate: true,
},
inputVal(newVal) {
console.log(`watch inputVal=${newVal}`)
},
},
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/273316.html