js高阶-响应式原理

what

  • 当变量变化的时候,涉及到这个变量的操作重新执行
  • 更多是针对对象类型进行监听(原始数据类型是不变的,任何的修改实质是创建了新值)

how

  • 响应式对象创建 Proxy
  • 响应式对象与依赖之间的映射关系 weakMap-map-set
  • 依赖函数收集

创建响应式对象

vue3

js 复制代码
//响应式对象创建

function reactive(obj) {

  return new Proxy(obj, {

    get(target, key) {

      const depend = getDepend(target, key);

      //依赖收集

      depend.addDepend();

      //返回

      return Reflect.get(target, key);

    },

    set(target, key, value) {

      const depend = getDepend(target, key);

      depend.notify();

      Reflect.set(target, key, value);

  

    },

  });

}

vue2方式

js 复制代码
//vue2的响应式操作

function reactive2(obj){

    Object.keys(obj).forEach(key=>{

        let value = obj[key]

        Object.defineProperty(obj,key,{

            get(){

                const depend = getDepend(obj,key)

                depend.depend()

                return value

            },

            set(newValue){

                const depend = getDepend(obj,key)

                depend.notify()

                value = newValue

            }

        })

    })

  

    return obj

}

对象-依赖关系

js 复制代码
let targetMap = new WeakMap(); // 响应式对象与依赖关系的映射 1.对象与属性的映射 2.属性与依赖函数的映射

  

class Depend {

  constructor() {

    this.reactiveFns = new Set();

  }

  //收集依赖

  addDepend() {

    if (activeReactiveFn) {

      this.reactiveFns.add(activeReactiveFn);

    }

  }

  //通知依赖

  notify() {

    this.reactiveFns.forEach((fn) => {

        if(fn){

          fn()

        }

    });

  }

}

function getDepend(target, key) {

  //1.根据target获取map

  let map = targetMap.get(target);

  if (!map) {

    map = new Map();

    targetMap.set(target, map);

  }

  //2.根据key获取depend

  let depend = map.get(key);

  if (!depend) {

    depend = new Depend();

    map.set(key, depend);

  }

  return depend;

}

依赖函数收集

js 复制代码
let activeReactiveFn = null; // 当前激活的响应式函数
//响应式函数收集---被watchFn收集的函数会成为响应式的依赖,当数据变化这些函数会被调用

function watchFn(fn) {

  activeReactiveFn = fn;

  fn();

  activeReactiveFn = null;

}

使用

js 复制代码
const obj = {

  name: "张三",

  age: 18,

};

//1.创建响应式对象

const objRef = reactive(obj);

//2.收集依赖函数

watchFn(()=>{

    console.log(objRef.name)

})

watchFn(()=>{

    console.log(objRef.age)

})
相关推荐
其实防守也摸鱼14 分钟前
前端应用的离线暂停更新策略:构建稳定可靠的渐进式部署方案
服务器·前端·数据库·学习·ai·命令行·linux系统
太平洋月光22 分钟前
Antv G2中自定义技巧📊
前端·数据可视化
shmily麻瓜小菜鸡33 分钟前
前端“伪防盗链”方案
前端·javascript·vue.js·bootstrap·echarts
mayaairi34 分钟前
JS数组完全指南(含十大操作详解)
开发语言·前端·javascript
IT_陈寒1 小时前
Python的线程池把我CPU跑满了,原来少传了个参数
前端·人工智能·后端
喜欢的名字被抢了1 小时前
写-Chrome-扩展时踩过的那些-MV3-的坑
前端·chrome
网安老伯1 小时前
网络安全基础要点知识介绍(非常详细),零基础入门到精通,看这一篇就够了
运维·前端·网络协议·web安全·网络安全·职场和发展
AndyHeee1 小时前
Linux 内核底层机制:设备树(Device Tree)的数据结构与内存组织
linux·前端·数据结构
wuqingshun3141591 小时前
springBoot是如何通过main方法启动web项目的?
前端·spring boot·后端
xxwl5851 小时前
HTML 小总结:从骨架到枝叶,系统掌握网页结构
前端·html