• vue3.0 响应式原理


    function isObject(target) {
        return typeof target === 'object' && target !== null
    }
    function hasOwn(target, key) {
        return Reflect.has(target, key)
    }
    let toProxy = new WeakMap()  //  存储 源对象 -> 代理对象
    let toRaw = new WeakMap() // 储存 代理对象 -> 源对象 
    let effectStacks = []  // 储存 effect
    function reactive(target) {
        // 创建代理对象 并返回
        let proxy = creatReactiveObject(target)
        return proxy
    }
    function creatReactiveObject(target) {
        if (!isObject(target)) return target
        // 判断是否是代理过的对象,或者是代理对象
        let proxy = toProxy.get(target)
        if (proxy) return proxy
        if (toRaw.has(target)) return target
        let handler = {
            get(target, key, receiver) {
                let res = Reflect.get(target, key, receiver)
                track(target, key)
                // 递归,如果res是对象 则继续代理
                return reactive(res)
            },
            set(target, key, value, receiver) {
                // 无效修改,直接返回
                if (hasOwn(target, key) && target[key] === value) return false
                let res = Reflect.set(target, key, value, receiver)
                trigger(target,key)
                return res
            },
            deleteProperty(target, key) {
                let res = Reflect.deleteProperty(target, key)
                console.log('deleteProperty');
                return res
            }
        }
        let observed = new Proxy(target, handler)
        toProxy.set(target, observed)
        toRaw.set(observed, target)
        return observed
    }
    /*
        {
            target: {
                key: new set
            }
        }    
    */
    let targetsMap = new WeakMap() // targetsMap 类似上述结构
    // 动态收集依赖
    function track(target, key) {
        let effect = effectStacks[effectStacks.length - 1]
        if(effect) {
            let depsMap = targetsMap.get(target)
            if(!depsMap) targetsMap.set(target, depsMap = new Map)
            let deps = depsMap.get(key)
            if(!deps) depsMap.set(key, deps = new Set)
            if(!deps.has(effect)) deps.add(effect)
        }
    }
    // 触发更新
    function trigger(target, key) {
        let depsMap = targetsMap.get(target)
        if(depsMap) {
            let deps = depsMap.get(key)
            if(deps) {
                deps.forEach(effect => {
                    effect()
                })
            }
        }
    }
    function effect(fn) {
        let effect = createEffect(fn)
        // 第一次 立即执行
        effect()
    }
    function createEffect(fn) {
        let effect = function () {
            run(effect, fn)
        }
        return effect
    }
    function run(effect, fn) {
        // 1.将effect 加入栈中,以便依赖收集 
        effectStacks.push(effect)
        // 2 执行fn,进行依赖收集
        fn()
        // 3 收集完毕,出栈
        effectStacks.pop()
    }
    
    let obj = {
        name: 'xx',
        deepObj: {
            a: 1
        },
        arr: [1, 2, 3]
    }
    
    let proxy = reactive(obj)
    effect(() => {
        console.log(proxy.name);
    })
    effect(() => {
        console.log(proxy.name);
    })
    proxy.name = 'yy'
    
    
    一个幽默的前端爱好者,记录下自己的心得体会
  • 相关阅读:
    简单讲解Asp.Net Core自带IOC容器ServiceCollection
    C#配置文件configSections详解
    学习Linq之前必须知道的几种语法糖
    学习Linq之前必须要了解的扩展方法
    学习学习学习学习!!!!!!!!!!!!
    SpringBoot自动配置原理
    OAuth2
    微服务搭建学习笔记(一) 认证中心搭建
    Vue 学习记录
    Vue实例(1)
  • 原文地址:https://www.cnblogs.com/little-oil/p/14976737.html
Copyright © 2020-2023  润新知