参考:
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的写法,大概有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){}, } }
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}`) }, },