5.watch方法的实现

watch方法的实现

Vue3中的watch方法用来监测数据的变化,然后执行某些操作,如监测用户的输入

原生方法的使用
  • 如果监控的是一个对象,则无法拿到新值和旧值
 const { effect, reactive, computed, watch } = Vue
        // const { effect, reactive,computed } = VueReactivity
        const state = reactive({
            firstName: 's',
            lastName: 'x'
        })
        watch(state, (newValue, oldValue) => {
            console.log(newValue, oldValue)
        })
        setTimeout(() => {
            state.lastName = 'xxx'
        }, 1000);

输入newValue和oldValue结果都为改变后的值

  • 如果监控的是一个对象,则会深度监控,即迭代监控对象的每一个属性,因此要尽量避免使用对象,减少资源浪费
  • 监控的是某个属性,则需写成函数式
   const { effect, reactive, computed, watch } = Vue
        // const { effect, reactive,computed } = VueReactivity
        const state = reactive({
            firstName: 's',
            lastName: 'x'
        })
        watch(()=>state.lastName, (newValue, oldValue) => {
            console.log(newValue, oldValue)
        })
        setTimeout(() => {
            state.lastName = 'xxx'
        }, 1000);
  • 其第二个参数可以传入三个参数,第三个参数是节流控制参数,方式数据多次改变异步并发
    • 当第一次改变state.age时,onCleanup中的回调不执行
    • 第二次改变时,执行onCleanUp中的回调,此时如果上一步的异步还在执行,则会使其不发生作用
 const state = reactive({ flag: true, name: 'jw ', age: 30 })
        let i = 2000;
        function getData(timer) {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(timer)
                }, timer);
            })
        }
        // 调用下一次的watch会执行上一次的onCleanup
        watch(() => state.age, async (newValue, oldValue,onCleanup) => {
            let f = false;
            onCleanup(()=>{ // 当我们把age= 32的时候会执行第一次的onCleanup中的回掉
                f = true;
            })
            i-=1000;
            let r = await getData(i); // 2000
            !f  && (document.body.innerHTML = r); 
        }, { flush: 'sync' });
        state.age = 31; // f = true   1s后应该渲染1000
        state.age = 32; //  f = false 0s后显示0 

新值和旧值会输出

watch方法的实现
  • watch传入两个参数,第一个参数为要监听的属性source,第二个参数为属性变化后的回调cb
  • 判断source类型,若是Proxy,则深度监控,交给监控函数,若是函数,则执行下一步
  • 创建job函数
    • 函数首先判断是否存在onCleanUp回调,存在则执行
  • 创建ReactiveEffect实例,第一个参数为source,第二个参数为job
  • 运行一次ReactiveEffect实例,获取原先值oldValue
  • 在job中运行ReactiveEffect实例,获取新值newValue,运行cb
  • 将newValue赋值给oldValue
import { isFunction, isObject } from "@vue/shared";
import { isReactive } from "./baseHandler";
import { ReactiveEffect } from "./effect";

function traversal(value,set = new Set()){
    if(!isObject(value)){
        return value
    }
    if(set.has(value)){
        return value
    }
    set.add(value)
    for(let key in value){
        traversal(value[key],set)
    }
    return value
}
export function watch(source,cb){
    let get = null;
    let cleanUp = null;
    let oldValue = null;
    if(isReactive(source)){
        get = ()=>traversal(source)
    }else if(isFunction(source)){
        get = source
    }

    const onCleanUp = (fn)=>{
        this.cleanUp = fn
    }

    let job = () => {
        cleanUp && cleanUp()
        let  newValue = effect.run
        cb(oldValue,newValue,onCleanUp)
        oldValue = newValue
    }
    let effect = new ReactiveEffect(get,job)
    oldValue = effect.run()
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

问也去

创作不易,感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值