找回密码
 立即注册
查看: 153|回复: 4

Vue2数据响应式入口函数的实现

[复制链接]

9

主题

37

回帖

151

积分

注册会员

积分
151
发表于 2022-9-19 21:39:10 | 显示全部楼层 |阅读模式
本帖最后由 13824597405 于 2022-9-19 21:42 编辑

响应式系统是通过 Object.defineProperty 把所有的数据转为getter/setter.
  • 在获取属性,触发 getter 时: 收集依赖 , 添加到依赖收集列表 deps
  • 在设置属性,触发 setter 时: 触发之前的收集的依赖


简单的代码实现:
  1. /*用于依赖收集, deps回调列表*/
  2. let deps = []
  3. let data={
  4.     test:"我是一个测试"
  5. }
  6. Object.defineProperty(data,"test",{
  7. /*获取的时候, 进行触发*/
  8. get(){
  9.     deps.forEach(fn=> fn())
  10. },
  11. /*设置的时候, 进行依赖收集*/
  12.     set(){
  13.    deps.push(fn)
  14. }
  15. })
复制代码


在Vue.js中给响应式属性添加一个 __ob__ 的属性用于证明属性是一个响应式的属性。


回复

使用道具 举报

9

主题

37

回帖

151

积分

注册会员

积分
151
 楼主| 发表于 2022-9-19 21:43:58 | 显示全部楼层
Vue中在 initData 函数最后一行调用响应式系统的入口:


  1. // observe data
  2. observe(data, true /* asRootData */);
复制代码

observe 函数的作用: 在把数据加入响应式系统之前, 对数据进行一些过滤

observe 的实现如下:
  1. /**
  2. * Attempt to create an observer instance for a value,
  3. * returns the new observer if successfully observed,
  4. * or the existing observer if the value already has one.
  5. */
  6. function observe(value, asRootData) {
  7.     /*检测value 是不是对象或者不是vNode的子类*/
  8.     if (!isObject(value) || value instanceof VNode) {
  9.         return
  10.     }
  11.     var ob;
  12.     /*通过 hasOwn 判断当前的value是否 "__ob__ 的属性"*/
  13.     /*判断value.__ob__是否是Observer的子类*/
  14.     /*条件成立, value已经是响应的式的*/
  15.     if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
  16.         ob = value.__ob__;
  17.      /*以上条件不成立, 说明还不是响应式的数据, 加入响应式系统 */
  18.     } else if (
  19.        /*shouldObserve实际上就是一个开关, 默认值为true*/
  20.        shouldObserve &&
  21.         /* 不是服务端渲染 */
  22.        !isServerRendering() &&
  23.        /*满足是数组或者原生Object对象*/
  24.        (Array.isArray(value) || isPlainObject(value)) &&
  25.        /*是否可以进行对象属性的扩展*/
  26.        Object.isExtensible(value) &&
  27.        /*不是vm根实例*/
  28.        !value._isVue
  29.     ) {
  30.         ob = new Observer(value);
  31.     }
  32.     /* asRootData 为根实例*/
  33.     if (asRootData && ob) {
  34.         /*vmCount是ob上的一个属性, 用于统计有多少个属性加入到了响应式系统当中.*/
  35.         ob.vmCount++;
  36.     }
  37.     return ob
  38. }
复制代码
回复

使用道具 举报

9

主题

37

回帖

151

积分

注册会员

积分
151
 楼主| 发表于 2022-9-19 21:46:40 | 显示全部楼层
上述代码首先对数据进行了限制:

  1. /*value , 直接返回是不是对象或者不是vNode的子类*/
  2. if (!isObject(value) || value instanceof VNode) {
  3.     return
  4. }
复制代码

value 不是对象,数组或者不是 vNode 的实例, 直接返回

对 value 通过 isObject(value) 进行了判断, isObject(value) 函数的实现:

  1. function isObject(obj) {
  2.     return obj !== null && typeof obj === 'object'
  3. }
复制代码

可以说明不仅是 object 对象, 也可以是数组
回复

使用道具 举报

9

主题

37

回帖

151

积分

注册会员

积分
151
 楼主| 发表于 2022-9-19 21:48:43 | 显示全部楼层
在接下来, if...else if 判断中
if 判断分为两步:

通过判断 value 是否有 __ob__ 的属性,并且 value.__ob__ 是 Observer 子类, 两者都成立, 说明已经是响应式的数据
上述的条件不成立, 在已经过if 的判断, 如果成立, 加入到响应式系统
在上面的代码, 第二个 if 判断, 进行了很多条件的限制:

shouldObserve 可以把他当做开关, true 可以加入到响应式系统, false 不能加入到响应式系统
  1. /**
  2. * In some cases we may want to disable observation inside a component's
  3. * update computation.
  4. */
  5. var shouldObserve = true;
  6. function toggleObserving(value) {
  7.     shouldObserve = value;
  8. }
复制代码

Object.isExtensible(value) 检测该对象是否可以扩展的对象, 怎么可以控制一个对象属性是否可以扩展属性
  1. /*通过 Object.seal() 可以控制*/
  2. Object.seal() // 方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要可写就可以改变。
复制代码

value._isVue 是 Vue 实例的标志, 所有的 Vue 实例都有这个标识, 所有的 Vue 的实例不能被观测.
  1. function initMixin(Vue) {
  2.     Vue.prototype._init = function (options) {
  3.         ...
  4.         // a flag to avoid this being observed
  5.         /*设置了一个标识, 避免被vm实例加入响应式系统 */
  6.         vm._isVue = true;
  7.        ...
  8.     };
  9. }
复制代码

经过一系列的数据的检测, 最终new Observer()加入到响应式系统当中:

  1. ob = new Observer(value);
复制代码
回复

使用道具 举报

0

主题

2

回帖

20

积分

新手上路

积分
20
发表于 2022-11-21 18:48:37 | 显示全部楼层
贺老大太牛逼拉
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|粤嵌技术交流空间

GMT+8, 2025-7-7 16:07 , Processed in 0.642954 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表