Vue3 刨析响应式原理

ref

目标

了解 Vue ,手写一个方法,实现响应式,并读懂响应式

源码

class MyRef {
    
    
  constructor(value) {
    
    
    this._value = value
  }
  // 访问器
  get value() {
    
    
    console.log('触发 getter 函数 访问');
    return this._value
  }
  // 读取器
  set value(newVal) {
    
    
    console.log('触发 setter 函数 修改');
    this._value = newVal
  }
}

const c1 = new MyRef(20)
console.log("c1:", c1);
setTimeout(() => {
    
    
  c1.value = 30
  console.log("c1:", c1);
}, 3000);

分析

1. 响应式

我们自定义了一个 class 类,并在 class 中写入 constructor 以及 get、set 方法,get value 做依赖收集并派发更新

  1. 第一次读取我们定义的响应式数据时,调用的时getter 方法输出如下
    在这里插入图片描述
  1. 经过修改响应式数据,我们调用 setter 方法,输出如下
    在这里插入图片描述

2. 发布 - 订阅者模式

接下来我们了解一下发布-订阅者模式

  • 首先我们先了解一下定义:
    1. 发布-订阅者 模式其实是一种 对象间一对多 的依赖关系(利用消息对列),一个调度中心对应多个订阅者
    2. 当一个对象的状态(state)发生改变时,所有依赖于它的对象都得到状态改变的通知
    3. 订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event Channel)
    4. 当发布者(Publisher)发布该事件(Publish Event)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码
  • 通俗易懂理解如下:
    1. 我们定义了一个函数,这个函数是一个发布者的事件,订阅者会直接调用发布者的事件,两者就会产生一个耦合,如果要解耦这两者之间的关系,就需要在两者中间加一个调度中心,也就是 Event Channel(一个中介) 。
    2. 发布订阅者模式是一个一对多的映射关系,即一个发布者对应多个订阅者
    3. 通常发布订阅者模式会有一个消息队列(先进先出——array)模式,即一个array中有多个方法,最先声明定义的函数最先调用
    4. 先定义好一个消息队列,然后根据需要的对象去订阅,当订阅的函数的状态发生改变时,对象不在主动触发,而是被动接收
    5. 举例:去书店订阅书籍(on),当没有货时,留下一个联系方式,一旦有了货源,店员就发射(emit)一个消息给用户,触发消息队列(message)去买书,然后off
    6. 实践:
      • 用websocket做一个长连接
      • addEventListener 事件绑定两个事件A和事件B,当你鼠标点击后,状态就会发生变化,状态发生变化,就要按照事件队列先后执行了事件A和事件B

3. 实现数据劫持

在这里插入图片描述

reactive

源码

我们都知道定义引用数据类型(object、array)都是用 reactive 去定义,当我们使用 ref 去定义时 Vue 底层会做一次转换,将 ref 定义的数据转换为 reactive ,下面是分别用 reactive、ref、shallowRef 定义的三种数据,输出结果如下:

const arr1 = reactive([1, 2, 3])
console.log('arr1: ', arr1);

const arr2 = ref([1, 2, 3])
console.log('arr2: ', arr2);

const arr3 = shallowRef([1, 2, 3])
console.log('arr3: ', arr3);

在这里插入图片描述

分析

使用 ref 定义的 array ,系统会转为 reactive ,通过 Vue 源码我们可以看到,在定义响应式数据时,做了一个判断,如果ref传入的是一个引用数据类型,就会将其转换为 reactive ,如果想要避免出现该情况,我们可以使用shallowRef,但是使用shallowRef 修改时,修改的 value 是响应式,但修改 value 值里面的属性不是响应式。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_53810245/article/details/131443074