首页 > 其他分享 >Vue3的响应系统

Vue3的响应系统

时间:2023-01-02 01:23:05浏览次数:41  
标签:target depsMap get 系统 响应 key Vue3 副作用 函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vuejs响应式</title>
</head>
<body>
    <div class="wrapper">
        <div class="text">0</div>
        <div class="input">
            <input id="input" type="text">
        </div>
    </div>
</body>
<script>
    // 用一个全局变量存储被注册的副作用函数
    let activeEffect
    // effect用于注册副作用函数
    function effect(fn) {
        // 当调用effect注册副作用函数时,将副作用函数fn赋值给activeEffect
        activeEffect = fn
        // 执行副作用函数
        fn()
    }
    // 存储副作用函数
    const bucket = new WeakMap()
    // 原始数据
    const data = { text: 'hello word' }
    // 对原始数据的代理
    const obj = new Proxy(data, {
        // 拦截读取操作
        get(target, key) {
            // 把副作用函数activeEffect添加到桶里去
            track(target, key)
            // 返回属性值
            return target[key]
        },
        // 拦截设置操作
        set(target, key, newVal) {
            // 设置值
            target[key] = newVal
            // 把副作用函数从桶里去除并执行
            trigger(target, key)
        }
    })
    effect(() => {
        document.querySelector('.text').innerHTML = obj.text
    })

    // 在get拦截函数内调用track函数追踪变化
    function track(target, key) {
        // 没有副作用函数,直接返回
        if (!activeEffect) return target[key]
        // 根据target从桶中取得depsMap,它也是夜歌Map类型:key --> effects
        let depsMap = bucket.get(target)
        // 如果不存在的depsMap,那么新建一个Map并与target关联
        if (!depsMap) {
            bucket.set(target, (depsMap = new Map()))
        }
        // 再根据key从deosMap中取得deps,他是一个Set类型
        // 里面存储这所有与当前key相关联的副作用函数:effects
        let deps = depsMap.get(key)
        // 如果deps不存在,同样新建一个与Set并与key关联
        if (!deps) {
            depsMap.set(key, (deps = new Set()))
        }
        // 将副作用函数存储至桶中
        deps.add(activeEffect)
    }
    // 在set拦截函数内调用trigger函数触发变化
    function trigger(target, key) {
        // 把副作用函数拿出来执行
        const depsMap = bucket.get(target)
        if (!depsMap) return
        const effects = depsMap.get(key)
        effects && effects.forEach(fn => fn())
    }

    let input = document.querySelector('#input')
    input.addEventListener('input', function () {
        obj.text = this.value
    })
</script>
<style>
    .wrapper {
        position: absolute;
        top: 30%;
        left: 20%;
    }
</style>
</html>



*来源于 Vue.js设计与实现 霍春阳 4.3 设计一个完善的响应系统

标签:target,depsMap,get,系统,响应,key,Vue3,副作用,函数
From: https://www.cnblogs.com/echohye/p/17019335.html

相关文章