watch
监听ref
let a = ref(0)
let b = ref(1)
watch(() => {
console.log('watch a+b', a.value + b.value)
})
watch(a, () => {
console.log('watch a', a.value + b.value)
})
setTimeout(
() => {
a.value++
}, 1000
)
setTimeout(
() => {
b.value++
}, 2000
)
默认是先执行一次, 不指定监听的数据源时, 只要关联数据变化, 就会执行, 指定监听源时, 只有指定的数据变化后才会执行
监听reactive
let a = reactive({count: 1})
let b = reactive({count: 2})
watch(() => {
console.log('a+b', a.count + b.count)
})
watch(() => a.count, () => {
console.log('a.count', a.count + b.count)
})
watch(() => a, () => {
console.log('a', a.count + b.count)
})
setTimeout(() => {
a.count++
}, 1000)
setTimeout(() => {
b.count++
}, 2000)
依然会先执行, 但是执行数据源必须精确指定
监听数组
let a = reactive({count: 1})
let b = ref(0)
watch(() => {
console.log('a+b', a.count, b.value)
})
watch(() => a.count, () => {
console.log('a.count', a.count, b.value)
})
watch(() => a, () => {
console.log('a', a.count, b.value)
})
watch(b, () => {
console.log('b', a.count, b.value)
})
watch(
[() => a.count, b],
([newCount, newValue], [oldCount, oldValue]) => {
console.log('new', newCount, newValue)
console.log('old', oldCount, oldValue)
}
)
setTimeout(() => {
a.count++
console.log('a change')
}, 1000)
setTimeout(() => {
b.value++
console.log('b change')
}, 2000)
stop 停止监听
let a = ref(0)
let stop = watch(() => {
console.log('a', a.value)
})
setTimeout(() => {
a.value++
console.log('change')
stop()
console.log('stop')
}, 1000)
setTimeout(() => {
a.value++
}, 2000)
setTimeout(() => {
a.count++
console.log('a change')
}, 3000)
clean
执行时机: watch重复调用时触发
let stop = watch(a, (newVal, oldVal, clean) => {
console.log('a', a.value)
clean(
() => {
console.log('clean')
}
)
}, {
// lazy: true
})
setTimeout(
() => {
a.value++
console.log('a change')
}, 1000
)
setTimeout(
() => {
a.value++
console.log('a change2')
}, 2000
)
watch 执行了三次, 所以clean会执行两次
lazy
不在初始化时执行watch中的函数
let stop = watch(a, (newVal, oldVal, clean) => {
console.log('a', a.value)
clean(
() => {
console.log('clean')
}
)
}, {
lazy: true
})
setTimeout(
() => {
a.value++
console.log('a change')
}, 1000
)
setTimeout(
() => {
a.value++
console.log('a change2')
}, 2000
)
watch执行了两次, clean执行了一次
使用stop时watch只执行了一次
let a = ref(0)
// 使用 clean 必须指定监听源
let stop = watch(a, (newVal, oldVal, clean) => {
console.log('a', a.value)
clean(
() => {
console.log('clean')
}
)
}, {
lazy: true
})
setTimeout(
() => {
a.value++
console.log('a change')
stop()
}, 1000
)
setTimeout(
() => {
a.value++
console.log('a change2')
}, 2000
)
watch执行了一次, 不会调用clean
使用stop时watch执行了多次
let a = ref(0)
// 使用 clean 必须指定监听源
let stop = watch(a, (newVal, oldVal, clean) => {
console.log('a', a.value)
clean(
() => {
console.log('clean')
}
)
}, {
lazy: true
})
setTimeout(
() => {
a.value++
console.log('a change')
}, 1000
)
setTimeout(
() => {
a.value++
console.log('a change2')
stop()
}, 2000
)
watch执行了两次, 但是在第二次执行完调用stop时, 会调用clean
一个使用clean节流的例子
不使用clean, 在频繁输入的时候, 会有大量无用请求
使用clean, 只有在两次改变间隔大于一定时间后才会真正请求
使用一个定时器模拟发出请求
<template>
<div>
<input v-model="s">
</div>
</template>
<script>
import {ref, watch} from 'vue'
function fetchData(s) {
return setTimeout(
() => {
console.log('s', s)
}, 100
)
}
export default {
name: "Watch",
setup() {
let s = ref('')
watch(s, (newVal, oldVal, clean) => {
let handler = fetchData(newVal)
// 每次重复执行时, 清空定时器
clean(() => clearTimeout(handler))
})
return {
s
}
}
}
</script>
来源:oschina
链接:https://my.oschina.net/ahaoboy/blog/3162331