watch监听
watch() 函数用来监视某些数据项的变化,从而触发某些特定的操作,使用之前需要按需导入:
import { watch } from 'vue'
基本用法
const count = ref(0)
// 定义 watch,只要 count 值变化,就会触发 watch 回调
// watch 会在创建时会自动调用一次
watch(() => console.log(count.value))
// 输出 0
setTimeout(() => {
count.value++
// 输出 1
}, 1000)
监视指定的数据源
监视 reactive 类型的数据源:
// 定义数据源
const state = reactive({ count: 0 })
// 监视 state.count 这个数据节点的变化
watch(
() => state.count,
//newCount新数据,oldCount旧数据
(newCount,oldCount) => {
/* ... */
}
)
监视 ref 类型的数据源:
// 定义数据源
const count = ref(0)
// 指定要监视的数据源
watch(count, (count, prevCount) => {
/* ... */
})
监视多个数据源
监视 reactive 类型的数据源:
const state = reactive({ count: 0, name: 'zs' })
watch(
[() => state.count, () => state.name], // Object.values(toRefs(state)),
([count, name], [prevCount, prevName]) => {
console.log(count) // 新的 count 值
console.log(name) // 新的 name 值
console.log('------------')
console.log(prevCount) // 旧的 count 值
console.log(prevName) // 旧的 name 值
},
{
lazy: true // 在 watch第一次被创建的时候,不执行回调函数中的代码
}
)
setTimeout(() => {
state.count++
state.name = 'ls'
}, 1000)
监视 ref 类型的数据源:
const count = ref(0)
const name = ref('zs')
watch(
[count, name], // 需要被监视的多个 ref 数据源
([count, name], [prevCount, prevName]) => {
console.log(count)
console.log(name)
console.log('-------------')
console.log(prevCount)
console.log(prevName)
},
{
lazy: true
}
)
setTimeout(() => {
count.value++
name.value = 'xiaomaolv'
}, 1000)
清除监视
在 setup() 函数内创建的 watch 监视,会在当前组件被销毁的时候自动停止。如果想要明确地停止某个监视,可以调用 watch() 函数的返回值即可,语法如下:
// 创建监视,并得到 停止函数
const stop = watch(() => {
/* ... */
})
// 调用停止函数,清除对应的监视
stop()
在 watch 中清除无效的异步任务
有时候,当被 watch 监视的值发生变化时,或 watch 本身被 stop 之后,我们期望能够清除那些无效的异步任务,此时,watch 回调函数中提供了一个 cleanup registrator function 来执行清除的工作。这个清除函数会在如下情况下被调用:
- watch 被重复执行了
- watch 被强制
stop了
Template 中的代码示例如下:
/* template 中的代码 */ <input type="text" v-model="keywords" />
Script 中的代码示例如下:
// 定义响应式数据 keywords
const keywords = ref('')
// 异步任务:打印用户输入的关键词
const asyncPrint = val => {
// 延时 1 秒后打印
return setTimeout(() => {
console.log(val)
}, 1000)
}
// 定义 watch 监听
watch(
keywords,
(keywords, prevKeywords, onCleanup) => {
// 执行异步任务,并得到关闭异步任务的 timerId
const timerId = asyncPrint(keywords)
// 如果 watch 监听被重复执行了,则会先清除上次未完成的异步任务
onCleanup(() => clearTimeout(timerId))
},
// watch 刚被创建的时候不执行
{ lazy: true }
)
// 把 template 中需要的数据 return 出去
return {
keywords
}
vue2中的watch监听
方法格式的监听
侦听数据变化,在watch节点,要监听谁,就把谁当作方法名
data:{username:''}
watch:{
//监听值username的变化
//newVal是变化后的新值,oldVal是旧值
username(newVal,oldVal){}
}
<input type="text" v-model="username">
<script>
const vm = new Vue({
el: '#app',
data: {
username: '1'
},
watch: {
//本质还是函数,监视谁就把谁作为函数名
username(newVal, oldVal) {
console.log(newVal, oldVal);
}
}
})
</script>
上面用的都是方法格式的侦听器,有缺点
- 无法在刚进入页面的时候自动触发(要使用对象格式的immediate选项)
- 无法深度监听对象内部每个属性的变化(要使用对象格式的deep选项)
对象格式的监听
对象格式的侦听器,使用immediate
var vm = new Vue({
el: '#app',
data: {
username: ''
},
watch: {
//定义对象格式的侦听器
username: {
//侦听器的处理函数
handler(newVal, oldVal) {
},
//自动立即触发,默认为false
immediate: true
}
}
})
对象格式的侦听器,使用deep
<script>
var vm = new Vue({
el: '#app',
data: {
//用户的信息对象
info: {
username: 'admin'
}
},
watch: {
//如果侦听对象,对象里面属性的变化不会被侦听到
info: {
handler(newVal) {
console.log(newVal);
},
//开启深度监听
deep: true
}
}
})
如果不需要深度监听,想只监听单个属性的变化,则必须包裹一层单引号(直接用方法格式)
'info.username'(newVal){}

本文详细介绍了Vue.js中watch监听的使用,包括基本用法、监视指定数据源、多个数据源以及清除监视。通过实例展示了如何监听ref和reactive类型的数据,以及如何在watch中清除无效的异步任务。同时,对比了方法格式和对象格式的watch监听,并指出了各自的优缺点。
2566

被折叠的 条评论
为什么被折叠?



