vue3响应系统的作用与实现

本文详细介绍了Vue响应式的概念,包括副作用函数和响应式数据。通过示例代码展示了如何实现数据与视图的绑定,重点解析了如何利用WeakMap和副作用函数栈来处理数据变化时的响应式更新,以及如何处理嵌套的effect和副作用函数清理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

响应式是vue的一个重要组成部分,它实现了数据与视图的绑定。接下我们就从相应数据跟副作用函数开始一步步了解vue的响应系统的设计与实现

副作用函数

副作用函数是指会产生副作用的函数

function effect(){
     document.body.innerText = "hellow";
}

当effect执行时,会改变body的内容,但除了effect,其他函数也可以访问到body的文本内容,所以effect函数会影响到其他函数读取body的内容,即说effect是一个副作用函数。

let a = 1
function effect(){
    var a = 2
}

副作用函数非常常见,像这种effect改变了其他函数也可以访问到的全局变量,影响了其他函数对它的读取,这也是一种副作用函数。可以理解为某个函数改变了其他函数对某个内容的访问结果,即这个函数是副作用函数

响应式数据

const obj = {text:'hellow'}
function effect (){
     document.body.innerText = obj.text;
}

当effect函数执行时,会改变body的文本内容。如果obj的值变化的时候都能触发effect,从而改变body的文本内容达到改变视图的效果,那我们则称obj是一个响应数据。
改变obj的时候,我们会触发到它的set操作,而读取的时候会触发到get操作。

如果我们可以拦截这两步操作,在读取obj.text的时候把副作用函数effect存储到一个桶里,在修改obj.text的时候再把这个副作用函数拿出来执行,便可以达到每当修改obj.text的时候都能改变视图的效果了。

在vue2中,vue采用了Object.defineProperty实现了响应系统,但Object.defineProperty只能监听指定key的value的变化,所以需要遍历整个对象从而监听所有key。vue3使用了Proxy代替了defineProperty解决了这一痛点。
这里我们用proxy来实现

  //用于存储副作用函数的桶
  const bucket = new Set();
  //原始数据
  const data = { text: "hellow" };
  //对原始数据的代理
  const obj = new Proxy(data, {
    get(target, key) {
      //将副作用函数丢进bucket
      if (effect) {
        bucket.add(effect);
      }
      //返回读取的值
      return target[key];
    },
    set(target, key, newVal) {
      //设置新属性值
      target[key] = newVal;
      //把副作用函数从桶取出并执行
      bucket.forEach((fn) => fn());
      //设置成功
      return true;
    },
  });

这时候执行effect之后,再改变obj.text的值的时候,会发数据响应视图,视图改变了。成功实现了一个响应数据。

注册副作用函数

在上面代码中,我们使用effect作为副作用函数,但实际中副作用函数不一定这么命名,甚至可能是一个匿名函数,所以我们需要一个注册副作用函数的流程

  //用一个全局变量存储被注册的副作用函数
  let activeEffect;
  //用于注册副作用函数
  function effect(fn) {
    activeEffect = fn;
    fn();
  }
  
  const obj = new Proxy
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值