【vue3源码笔记1】- 响应式

Vue | 2020-12-27 12:23:55 385次 1次

开篇之前先看下 mvvm 实现

精简版vue3


代码结构

compiler-core: 平台无关的编译

compiler-dom: 浏览器的编译

compiler-sfc: 单文件编译部分

compiler-ssr: 服务端渲染编译相关


reactivity:  响应系统


runtime-core: 运行时与创建实例相关代码

runtime-dom: 针对浏览器的运行时。包括DOM API,属性,事件处理等

runtime-test: 测试代码


server-renderer: 服务端渲染

shared: 工具库

size-check: 测试代码体积

template-explorer: 内部使用的编译文件浏览工具


vue: 主入口文件

通过文件结构的划分,可以看出 vue 包含三大模块:响应式系统、编译模块、运行时(调度、diff 等)


源码调试

通过 yarn build -s 打包 vue3 (生成 source map),代码中通过 umd 方式引入调试。

其次是通过【单元测试】中的测试用例来辅助理解。 


Reactive

Vue2 通过 observer 进行数据的变化监听,watcher 通过 dep 收集自身,保存界面渲染回调,当有数据变化时,会触发 dep 中任务列表,从而更新页面。watcher 和 compiler 绑定,watcher 绑定到 dep 静态属性上之后,触发一次数据获取,在 observer 进行了 watch 依赖收集,从而可以监听数据变化触发这些依赖。

Vue3 核心是通过 Proxy 进行数据的劫持,取值 track,赋值 trigger。当在 effect 中取值时,存储的是用户创建的各个对象  

targetMap(weakMap)【多次的reciver】 --> depsMap(Map)【reciver数据中不同的键】 --> dep(Set)[用来发布订阅的执行 effect] 

      赋值时候,通过如上的数据结构,找到修改key,来执行所有的effect回调即可,整体设计结构如下图:

未命名1615218679.png


避免多个 effect 中再次设置被监听的值赋值操作导致的重复渲染问题,可以通过一个栈记录所有的信息,避免重复添加,再通过 activeEffect 判断避免重复执行。


Ref

    function ref(raw){
        const r = {
            get value(){
                track(r, 'value');
                return raw;
            },
            set value(newValue){
                raw = newValue;
                trigger(r, 'value');
            }
        }
        return r;
    }


Computed

    function computed(getter){
        const res = ref();
        watchEffect(() => {
            res.value = getter();
        })
        return res;
    }

响应式的部分内容比较清晰简单,就是负责数据的响应监听,具体代码请参考 svu 的简易实现。

1人赞

分享到: