$watch()、watch()的使用方式与功能 完全等效,在此案例只写composition api的watch()
本章涉及内容:概念、watch的使用方式、功能讲解。
- 概念:
- watch API 与选项式 API this.$watch (以及相应的 watch 选项) 完全等效。
- watch 需要侦听特定的数据源,并在单独的回调函数中执行副作用。默认情况下,它也是惰性的——即回调仅在侦听源发生变化时被调用。
- 缓冲回调:缓冲回调不仅可以提高性能,还有助于保证数据的一致性。在执行数据更新的代码完成之前,侦听器不会被触发。简单来说,同步修改数据时,修完操作执行完毕后才会触发回调。注意是同步!所以异步操作的时候,要注意多次触发watch的问题。(所有同步操作为1次,异步操作有几次就触发多少次监听!!)
- 直接传入ref对象,会自动解包 .value
功能1:停止侦听
此处监听的ref对象,传入的是ref对象则会自动解包 .value(基于源码的解释)
<script lang='ts' setup>
import { watch,ref } from 'vue';
let count = ref(0)
//! 关于 watch() 返回的 StopHandle 函数,调用stop()将会停止侦听。
let stop = watch(count, (newValue, oldValue,InvalidateCbRegistrator) => {
console.log('watch : count-:' + newValue, oldValue)
})
setTimeout(() => stop(), 3333); // stop() 停止侦听
</script>
功能2:监听 reactive() 的对象:
直接监听reactive声明的proxy对象,最终vue会默认赋值为true,所以自己传什么都没用。(基于源码的解释)
<script lang='ts' setup>
import { watch,reactive } from 'vue';
let proxy1 = reactive({})
watch(proxy1, (newValue, oldValue) => {
console.log('proxy1--',newValue , oldValue )
},{
deep:'干啥勒,对我做啥我都不从' //! 基于上述解释,此处传什么都是无效的,最终会被默认覆盖为true
})
</script>
功能3:监听嵌套对象的某个属性 (传入函数)
单独监听嵌套的某个属性 则需要传入函数的返回值
<script lang='ts' setup>
import { watch,reactive } from 'vue';
// reactive ref都行,看了 refs 篇章你也知道其原理
let proxy1 = reactive({t1:'嵌套数据'})
watch(()=>proxy1.t1, (newValue, oldValue) => {
console.log(newValue, oldValue)
})
</script>
功能4:监听多个源的形式 (传入数组)。
<script lang='ts' setup>
import { watch,reactive } from 'vue';
let data1 = reactive({t1:'t1嵌套数据'})
let data2 = reactive({t2:'t2嵌套数据'})
watch([data1,data2], (newValue, oldValue) => {
console.log(newValue, oldValue)
})
</script>
- 功能5:第三个参数的3种形式:
- flush 关于这个参数的讲解:首先 选项式api( watch:{} ) 、$watch() 、 watch()、watchEffect() 4个都能用!
- pre 模式下,指定的回调在模板渲染前被调用,所以立马获取对应的内容,将不会是最新的!!
- post 模式下,将回调推迟到模板渲染之后的,这时候用$ref获取对应内容则会是最新的,等于 pre 模式下用 nextTice()
- sync 就不多说了,回调改为同步调用,即取消 <缓冲回调> 这个功能
- 'pre' 和 'post' 回调使用队列进行缓冲,这也是为什么<同步>多次修改后,只触发最后一次监听回调的原因。
<script lang='ts' setup>
import { watch,reactive } from 'vue';
let data1 = reactive({t1:'t1嵌套数据'})
watch(data1, (newValue, oldValue) => {
console.log('data1--',newValue, oldValue)
},{
deep:false, // 用讲?不懂看选项API的watch
immediate:false, // 用讲?不懂看选项API的watch
flush:'post' // 'pre' | 'post' | 'sync' // 默认值是'pre'
})
</script>
功能6:callback的第三个参数
解释看代码内的注释
<script lang='ts' setup>
import { watch,reactive } from 'vue';
let data1 = reactive({t1:'t1嵌套数据'})
let stop = watch(data1, (newValue, oldValue,InvalidateCbRegistrator) => {
InvalidateCbRegistrator(()=>{
// 在watch的 cb 执行之前,先会执行这个回调!。
// 但是,第一次 watch 的cb执行后,该回调才正式开始生效,也就是说第一次是不执行的。
// 当调用stop的时候,也会执行 InvalidateCbRegistrator ,最后的悲鸣~~
console.log('执行了');
})
})
data1.t1 = 1
settimeout(() => data1.t1 = 321, 1500)
setTimeout(() => stop(), 3333); // stop() 停止侦听
</script>
其他vue3 选项式api、组合式api、全局/应用api学习经验分享