Vue.js Watch经常失效的场景与解决方案
在使用Vue.js的过程中,watch是非常常用的一个功能,它可以监听数据的变化并实现相应的操作,但是在实际开发中使用watch时可能会出现失效的情况,本文将讲解Watch失效的场景及解决方案。
Watch 失效的场景
- 深度监听
在Vue.js中,许多组件和工具可以帮助我们在数据更改时实时更新视图。这是通过“依赖追踪”来实现的,系统知道哪些属性被使用,当它们更改时重新渲染DOM。
但有些情况下默认的依赖跟踪可能不够粗粒度,需要开发者显式地告诉Vue.js去深度监听某些属性的变化。
当一个对象被监听,Vue.js默认只监听这个对象的第一层属性。如果这个对象内部嵌套了一个新的对象,Vue.js并不会去监听这个新对象内部的变化。这时如果我们希望监听这个新对象内部属性的变化,就需要使用深度监听。
watch: {
obj: {
handler: function (val) {
...
},
deep: true // 监听 obj 对象内部的变化
}
}
- 异步更新
在某些场景下,我们需要异步更新数据,比如在获取数据后异步更改某个属性的值。但是此时使用watch去监听该属性的变化可能会失效。
这是因为在异步更新数据时,Vue.js可能会无法正确监听到属性值的变化,因为它已经赋值为一个新对象,而watch监听的是原属性,两者并不是同一个实例。
这时我们可以通过 $nextTick 方法去确认异步更新成功后再去处理 watch 的监测逻辑。
methods: {
async fetchData() {
const data = await API.getData()
this.obj = data // 异步更新 obj 对象
this.$nextTick(() => {
// $nextTick 保证数据更新渲染完成
// 处理 obj 属性的 watcher 逻辑
})
}
}
Watch 失效的解决方案
- 直接监听数据属性
由于使用深度监听可能会导致性能问题,我们可以去掉 deep 属性,直接监听数据属性。
这种方式可以避免深层次对象引起监听器失效的问题。当数据层次较深时,如果你需要层层深入去监听变化,就会严重影响性能。
watch: {
obj: function (val) {
...
}
}
- 自定义 computed
如果watch失效,我们可以将原本应该在watch中触发的逻辑放在自定义的 computed 中去操作,这种方式更加符合Vue.js的设计思路,也更加易于维护。
computed: {
objWatch() {
return this.obj // 直接返回 obj 对象
}
},
methods: {
doSomething() {
// objWatch 变化时触发逻辑
}
}
示例1
我们有一个表单,其中包含一个input框,需要用户输入一个数字,当用户输入的数字是偶数时和奇数时分别触发不同的操作。代码如下:
<template>
<div>
<input v-model="number" type="number">
</div>
</template>
<script>
export default {
data() {
return {
number: null,
}
},
watch: {
number: function(newVal) {
if (newVal % 2 === 0) {
alert('偶数')
} else {
alert('奇数')
}
},
},
}
</script>
在此时,我们已经使用watch监听了number属性的变化,但是不管我们输入的数字是奇数还是偶数,页面上都会弹出偶数的alert提示框。这是因为Vue.js无法正确监听到属性值的变化。
此时,我们可以使用selfcomputed的方法去实现该功能:
<template>
<div>
<input v-model="number" type="number">
</div>
</template>
<script>
export default {
data() {
return {
number: null,
}
},
computed: {
selfWatch() {
if (this.number % 2 === 0) {
return '偶数'
}
return '奇数'
},
},
methods: {
doSomething() {
alert(this.selfWatch)
},
},
}
</script>
示例2
我们有一个异步请求,在请求成功后需要更新页面上的数据。代码如下:
<template>
<div>{{ obj }}</div>
</template>
<script>
export default {
data() {
return {
obj: null,
}
},
watch: {
obj: function(newVal) {
this.doSomething() // 触发操作
},
},
methods: {
async fetch() {
const res = await API.getData()
this.obj = res.data
},
doSomething() {
console.log('doing something')
},
},
}
</script>
在此时,我们使用watch去监测obj的变化,但是由于fetch是一个异步请求,我们不能确定obj已经成功更新了。因此,此时watch会失效。此时我们可以使用Vue.js提供的 $nextTick 方法去确认异步更新成功后再去处理 watch 的监测逻辑。
<template>
<div>{{ obj }}</div>
</template>
<script>
export default {
data() {
return {
obj: null,
}
},
watch: {
obj: function(newVal) {
this.doSomething() // 触发操作
},
},
methods: {
async fetch() {
const res = await API.getData()
this.obj = res.data
this.$nextTick(() => {
// $nextTick 保证数据更新渲染完成
// 处理 obj 属性的 watcher 逻辑
})
},
doSomething() {
console.log('doing something')
},
},
}
</script>
结语
在使用Vue.js的过程中,watch是一个非常常用的功能。但是在使用时也要慎重,避免失效的情况。通过对本文的学习,你将能够更好的使用watch、自定义computed和$nextTick等常用方法,为你的项目注入更多的灵活性和高效性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue.js watch经常失效的场景与解决方案 - Python技术站