美文网首页
vue.js设计与实现(四)-响应系统

vue.js设计与实现(四)-响应系统

作者: 幸宇 | 来源:发表于2022-12-28 18:55 被阅读0次

    1、简单的响应架构设计实现:
    背景:有一个函数effect实现document.body.innerText的文本内容改变,body中的文本内容和一个data对象中的text属性相互绑定,当data对象中text属性改变时,body中的文本做出相应的改变;
    设计原理:采用Proxy代理data数据,当代理对象获取到data属性text时,将effect函数放置一个桶中,即一个new Set() 的数据结构中,当代理对象改变data中的数据时,去遍历执行Set结构中的函数对象,从而达到更改body文本中的目的;

        const data = {text:'hello world'}
        const bucket = new Set();
        const obj = new Proxy(data,{
            get(target,key){
                bucket.add(effect)
                return target[key]
            },
            set(target,key,newVal){
                target[key] = newVal
                bucket.forEach(fn=>fn())
                return true
            }
        })
        function effect(){
            document.body.innerText = obj.text
        }
        // 触发读取操作
        effect()
        // 1秒后修改
        setTimeout(()=>{
            obj.text = 'hello vue3'
        },1000)
    

    完善结构处理:

    const data = {text:'hello world'}
        const bucket = new WeakMap()
        // 定义一个全局变量用来存储被注册的副作用函数
        let activeEffect;
        // 用来注册副作用函数
        function effect(fn){
            activeEffect = fn;
            fn()
        }
        function track(target,key){
            if(!activeEffect) return
            let depsMap = bucket.get(target)
                if(!depsMap){
                    bucket.set(target,depsMap = new Map())
                }
                let deps = depsMap.get(key)
                if(!deps){
                    depsMap.set(key,deps = new Set())
                }
                deps.add(activeEffect)
        }
        function trigger(target,key){
            const depsMap = bucket.get(target)
            if(!depsMap) return
            const effects = depsMap.get(key)
            effects && effects.forEach(fn=>fn())
        }
        const obj = new Proxy(data,{
            get(target,key){
                track(target,key)
                return target[key]
            },
            set(target,key,newVal){
                target[key] = newVal
                trigger(target,key)
            }
        })
        effect(
            ()=>{
                // console.log('effect run',bucket)
                document.body.innerText = obj.text;
            }
        )
        setTimeout(()=>{
            obj.notExist = 'hello vue3'
        },1000)
    

    相关文章

      网友评论

          本文标题:vue.js设计与实现(四)-响应系统

          本文链接:https://www.haomeiwen.com/subject/isdzqdtx.html