likes
comments
collection
share

深入了解Vue数据响应式原理

作者站长头像
站长
· 阅读数 78

虽然之前看了一些博主写的文章,但是有时候对Vue响应式原理这块讲起来还是支支吾吾,所以决定重新再整理一下。

Vue的响应式原理是基于发布订阅模式实现的。所以先来了解一下发布订阅模式【Publish-Subscribe Pattern】

了解前端常见的两种设计模式

发布-订阅模式 Publish-Subscribe Pattern

由发布者Publisher、订阅者列表Subscriber、消息队列/调度中心Event Channel组成的形式。 发布者Publisher和订阅者Subscriber之间是互不相识,不直接通信交流的,而是通过消息队列进行。

可以理解为:某博主(发布者)发布了一个短视频在短视频平台(消息队列)上,每天上班搬砖的打工人(订阅者)趁着吃饭的时间,刷刷短视频,发现该博主的视频非常优秀有内容,于是在该短视频平台上订阅关注了该视频博主。然后该博主只要更新了视频,你就能接收到通知。

深入了解Vue数据响应式原理

特点

  • 松解耦:发布者订阅者通过中介进行通信,互不知晓对方存在。降低了组件间的耦合度,使得更容易理解维护和扩展。
  • 扩展性:由于解耦性,可以更容易扩展。新增发布者或订阅者不影响现有组件。
  • 灵活性:允许任何数量的发布者订阅者存在,支持多对多通信。删除、修改、新增不影响系统运行。
  • 异步通信:支持异步通信,能更高效处理消息,提高响应性。

举🌰

class eventChannel {
  constructor() {
    this.msgMap = {}
  }
  publish(name, param) {
    const msg = this.msgMap[name]
    if (msg) {
      msg.subscribeList.forEach(subscribe => {
        subscribe.callback(param)
      })
    }
  }
  subscribe(name, callback) {
    const msg = this.msgMap[name]
    if (msg) {
      msg.subscribe.push({callback})
    } else {
      this.msgMap[name] = {
        name,
        subscribeList: [{callback}]
      }
    }
  }
}

观察者模式 Observer Pattern

面试有时候会被问到观察者模式和发布-订阅模式之间有什么不同。简单的说:观察者(Observer)直接订阅(Subscribe)主题(Subject),而当主题被激活的时候,会触发(Fire Event)观察者里的事件,没有中介代替传递消息。

观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新。观察者模式属于行为型模式,行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯。

深入了解Vue数据响应式原理

特点

  • 松耦合:实现了主题和观察者之间的松耦合。
  • 一对多关系:一个主题可以有多个观察者。
  • 可扩展性:可以随时添加新的观察者,或删除现有观察者。
  • 实时性:主题发生变化时,观察者能立刻收到通知。

举🌰

let observerIds = 0
// 被观察者
class Subject {
  constructor() {
    this.observeres = []
  }
  addObservere(observer) {
    this.observeres.push(observer)
  }
  removeObservere(obs) {
    this.observeres = this.observeres.filter(observer => observer !== obs )
  }
  notify(data) {
    this.observeres.forEach(observer => observer(data))
  }
}

// 观察者
class Observer {
  constructor() {
    this.id  = observerIds++
  }
  update(ob) {
    // ...
  }
}

Vue2 数据响应式原理

深入了解Vue数据响应式原理

Vue2的数据对象是通过Object.defineProperty进行数据劫持, 将其对象属性转化为响应式属性。同时,为每个属性创建一个Dep对象,收集当前属性的依赖关系。这里的Dep就相当于上文发布订阅模式中讲到的调度中心。

当读取数据时会触发getter,修改数据时会触发setter。Watcher对象作用是建立依赖关系,检测数据变化,并在数据变化时执行相应的更新操作。Watcher机制是基于异步更新的,这样能避免频繁更新,提高性能和优化用户体验。

Vue3 数据响应式原理

Vue3 是基于proxy的Observer,通过Proxy拦截对象属性变化,通过Reflect对原对象属性进行操作。

Proxy:在目标对象之前假设一层拦截,可以对外界的访问进行改写。可以通过其get捕获器拦截读取对象属性,通过set捕获器拦截对象属性赋值。

Reflect:提供了一组和Objct类似的方法,用于操作对象。Vue3中主要配合Proxy进行操作,以获取/设置代理对象属性值。

深入了解Vue数据响应式原理

Vue3使用Proxy替代Obejct.defineProperty,解决了以下问题:

  1. 优化数组监听:Proxy可以直接拦截数组索引设置和长度变更。
  2. 嵌套对象处理:Vue2需要递归对每个子对象进行数据拦截,而Proxy代理整个对象,无论层级多深都能有效追踪数据变化。
  3. 全面属性监听:Vue2只能监听已注册的属性,Vue3能对对象属性的新增删除修改做全面监听和数据变化追踪。
转载自:https://juejin.cn/post/7361317042567806985
评论
请登录