Vue3 响应式原理

Vue3 响应式原理_第1张图片

 响应式原理

Vue2 使用的是 Object.defineProperty  Vue3 使用的是 Proxy

2.0的不足

对象只能劫持 设置好的数据,新增的数据需要Vue.Set(xxx)  数组只能操作七种方法,修改某一项值无法劫持。

reactive和effect的实现

export const reactive = (target:T) => {
    return new Proxy(target,{
        get (target,key,receiver) {
          const res  = Reflect.get(target,key,receiver) as object


          return res
        },
        set (target,key,value,receiver) {
           const res = Reflect.set(target,key,value,receiver)


           return res
        }
    })
}

 Vue3 的响应式原理依赖了 Proxy 这个核心 API,通过 Proxy 可以劫持对象的某些操作。

effect track trigger

实现effect 副作用函数

let activeEffect;
export const effect = (fn:Function) => {
     const _effect = function () {
        activeEffect = _effect;
        fn()
     }
     _effect()
}

 使用一个全局变量 active 收集当前副作用函数,并且初始化的时候调用一下

实现track

const targetMap = new WeakMap()
export const track = (target,key) =>{
   let depsMap = targetMap.get(target)
   if(!depsMap){
       depsMap = new Map()
       targetMap.set(target,depsMap)
   }
   let deps = depsMap.get(key)
   if(!deps){
      deps = new Set()
      depsMap.set(key,deps)
   }

   deps.add(activeEffect)
}

执行完成成后我们得到一个如下的数据结构 

Vue3 响应式原理_第2张图片 

实现trigger

export const trigger = (target,key) => {
   const depsMap = targetMap.get(target)
   const deps = depsMap.get(key)
   deps.forEach(effect=>effect())
}

 当我们进行赋值的时候会调用 set 然后 触发收集的副作用函数

import {track,trigger} from './effect'


export const reactive = (target:T) => {
    return new Proxy(target,{
        get (target,key,receiver) {
          const res  = Reflect.get(target,key,receiver) as object

          track(target,key)

          return res
        },
        set (target,key,value,receiver) {
           const res = Reflect.set(target,key,value,receiver)
 
           trigger(target,key)

           return res
        }
    })
}

 给 reactive 添加这两个方法

测试代码





    
    
    
    Document




    

递归实现reactive

import { track, trigger } from './effect'

const isObject = (target) => target != null && typeof target == 'object'

export const reactive = (target: T) => {
    return new Proxy(target, {
        get(target, key, receiver) {
            const res = Reflect.get(target, key, receiver) as object

            track(target, key)

            if (isObject(res)) {
                return reactive(res)
            }

            return res
        },
        set(target, key, value, receiver) {
            const res = Reflect.set(target, key, value, receiver)

            trigger(target, key)

            return res
        }
    })
}




    
    
    
    Document




    

 Vue3 响应式原理_第3张图片

 

你可能感兴趣的:(Vue3,vue.js,前端,javascript)