Observer

我们在打断点的时候会发现在遍历对象的时候会重新new Observer,而且这个Observer拥有自己的dep对象,既然我们都能对数据进行监控,为啥还需要Dep这个东西呢

先说结论,其实这个是为了我们新增数据如 $set 和 数组操作来实现将新数据绑定的

我们想想 如果一个数据是新进来的,他是不会之前initData的时候将数据进行双向绑定的,那么我们怎么能够通过Dep通过notify来提醒视图更新呢,这时候我们想起来Dep的作用,但是新数据没有Dep,怎么通过Dep的notify来提示数据改变呢。

  1. Vue的实现方法是通过判断子对象为obj的时候,在observer()的时候为数据添加一个dep和定义自己的__ob__属性
// new Observer
export class Observer {value: any;dep: Dep;vmCount: number; // number of vms that have this object as root $dataconstructor(value: any) {this.value = value;// 实例化一个 Depthis.dep = new Dep();this.vmCount = 0;// 定义一个__ob__ 属性def(value, "__ob__", this);//... 省略下面一些东西}
}
  1. 在遍历对象的时候,如果是对象的话给对象自己new Observer()然后配上自己的Dep
export function defineReactive(obj: Object,key: string,val: any,customSetter ? : ? Function,shallow ? : boolean
) {//... 省略一些东西// 判断val是否是对象,如果是对象给对象new observer()和付给一个dep对象// 这个childOb 就是为了绑定相对应的dep 相当于我在外面加了一个Dep,如果有新数据自己通过它相应Watcherlet childOb = !shallow && observe(val);//... 省略一些东西
}
  1. 通过上诉两个过程的执行,最后达成的目的就是每个对象都有自己的__ob__和dep属性
  2. 在使用数据的时候 会通过get的方法 会通过childOb.dep 来添加Wacher
if (childOb) {// 对象中嵌套对象的观察者对象,如果存在也对其进行依赖收集childOb.dep.depend();//... 处理其他
}
  1. 这时候我们看看set和delete方法,都是通过__ob__ 这个元素拿到dep来进行notify的
export function set(target: Array < any > | Object, key: any, val: any): any {if (process.env.NODE_ENV !== "production" &&(isUndef(target) || isPrimitive(target))) {warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`);}// 如果 target 是数组,利用数组的 splice 变异方法触发响应式// Vue.set([1,2,3], 1, 5)if (Array.isArray(target) && isValidArrayIndex(key)) {// 修改数组的长度, 避免数组索引 key 大于数组长度导致 splcie() 执行有误target.length = Math.max(target.length, key);target.splice(key, 1, val);return val;}// 如果 key 已经存在 target 中,更新 target[key] 的值为 valif (key in target && !(key in Object.prototype)) {target[key] = val;return val;}// 读取一下 target.__ob__,这个主要用来判断 target 是否是响应式对象const ob = (target: any).__ob__;// 需要操作的目标对象不能是 Vue 实例或 Vue 实例的根数据对象if (target._isVue || (ob && ob.vmCount)) {process.env.NODE_ENV !== "production" &&warn("Avoid adding reactive properties to a Vue instance or its root $data " +"at runtime - declare it upfront in the data option.");return val;}// 当 target 不是响应式对象,并且对象本身不存在这个新属性 key// 新属性会被设置,但是不会做响应式处理if (!ob) {target[key] = val;return val;}// target 是响应式对象,并且对象本身不存在这个新属性 key// 给对象定义新属性,通过 defineReactive 方法将新属性设置为响应式// ob.dep.notify 通知更新defineReactive(ob.value, key, val);ob.dep.notify();return val;
}/*** Delete a property and trigger change if necessary.*/
// 通过 Vue.delete 或 vm.$delete 将 target 的 key 属性删除
export function del(target: Array < any > | Object, key: any) {if (process.env.NODE_ENV !== "production" &&(isUndef(target) || isPrimitive(target))) {warn(`Cannot delete reactive property on undefined, null, or primitive value: ${(target: any)}`);}// 如果 target 是数组,通过数组的变异方法 splice 删除对应对应的 key 项,并且触发响应式更新// Vue.delete([1,2,3], 1)if (Array.isArray(target) && isValidArrayIndex(key)) {target.splice(key, 1);return;}// 读取一下 target.__ob__,这个主要用来判断 target 是否是响应式对象const ob = (target: any).__ob__;// 需要操作的目标对象不能是 Vue 实例或 Vue 实例的根数据对象if (target._isVue || (ob && ob.vmCount)) {process.env.NODE_ENV !== "production" &&warn("Avoid deleting properties on a Vue instance or its root $data " +"- just set it to null.");return;}// 如果 target 上不存在 key 属性,直接结束if (!hasOwn(target, key)) {return;}// 直接通过 delete 删除对象的 key 项delete target[key];// target 不是响应式对象,不需要通知更新if (!ob) {return;}// target 是响应式,通知更新ob.dep.notify();
}
  1. 而且数组的更新其实也是用了这一点,vue会重新定义数组的7中方法
methodsToPatch.forEach(function (method) {// 缓冲原始数组的方法const original = arrayProto[method]def(arrayMethods, method, function mutator(...args) {const result = original.apply(this, args)const ob = this.__ob__// push 和 unshfit 和 splice 都会插入新元素,其中splice的第二个参数开始表示插入的元素值let insertedswitch (method) {case 'push':case 'unshift':inserted = args // 比如:args 是 [{...}]breakcase 'splice':inserted = args.slice(2)break}// 对插入的元素进行响应式处理if (inserted) ob.observeArray(inserted)// 通过 dep.notify 通知更新ob.dep.notify()return result})
})

重点

  1. 给每个对象一个Dep__ob__
  2. 而且这个对象是通过childobj给上一级
  3. childobj是为了让每个对象都能够拥有上一级get的时候拥有的Watcher,这个时候__ob__Dep也就用了Watcher
  4. 新增元素的时候我们可以通过这个__ob__Depnotify是视图发生改变等操作

逻辑很绕,如果大佬有妥当的描述,欢迎指出相关错误以及描述点

Vue2 中 Observer 一些探究相关推荐

  1. java lock的原理,Java中Lock原理探究

    在对于lock锁的使用上,很多人只是掌握了最基础的方法,但是对实现的过程不是很清楚.这里我们对lock锁功能的实现进行分析,以ReentrantLock为例,分析它的锁类型,并对相关的调用方法进行展示 ...

  2. 资源放送丨《 MySQL中的索引探究 - 2020云和恩墨大讲堂》PPT视频

    前段时间,墨天轮邀请到云和恩墨应用架构产品部总经理 巩飞 分享了直播<MySQL中的索引探究>,在这里我们共享一下PPT和视频,供大家参考学习. 本次分享讲述MySQL的索引原理,不同存储 ...

  3. 直播预告丨MySQL中的索引探究

    MySQL中的索引探究 - 08/05 本次分享讲述MySQL的索引原理,不同存储引擎对索引的支持情况.同时探究大家普遍关心的问题:MySQL在哪些操作中会用到索引?InnoDB引擎对索引做了哪些扩展 ...

  4. vue2中vant实现网易云音乐案例-附带所有源码

    vue2中vant实现网易云音乐案例-附带所有源码 前言 学习笔记以及源码下载gitee: https://gitee.com/xingyueqianduan/vantmsicdemo 下载下来的内容 ...

  5. vue2中使用axios,以及axios拦截器的配置

    目录 一.vue2项目中如何实现异步请求 1.axios:是一个基于Promise的网络请求库.既可以在node.js(服务器端)使用,也可以在浏览器端使用 2.vue中的使用方法 ​ (2)引用方法 ...

  6. vue2 通过 axios  访问koa2,从mysql 拿到数据更新vue2中的内容

    vue2 通过 axios  访问koa2,从mysql 拿到数据更新vue2中的内容 axios 类似ajax 注意红色字体 node --inspect index.js (启用debug模式) ...

  7. vue2中使用Leaflet实现单个或多个marker图标

    vue2中使用Leaflet实现单个或多个marker图标 初始化一个vue项目 在 vue 中安装 Leaflet 在main.js中引入leaflet 加载一个简单的地图框架 添加一个或多个Mar ...

  8. simca算法 matlab,SIMCA分类法中主成分分析算法探究.doc

    SIMCA分类法中主成分分析算法探究 SIMCA分类法中主成分分析算法探究 摘要:模式识别是研究用计算机模拟人的识别能力,对不同类型形式的数据进行描述.分类.识别等有关的理论和方法.SIMCA方法是基 ...

  9. vue2中,使用vite流程之应用前端构建工具vite和vite-plugin-vue2插件

    vue2中,使用vite流程之应用前端构建工具vite和vite-plugin-vue2插件 Vite 官方中文文档--https://cn.vitejs.dev/ vite-plugin-vue2包 ...

最新文章

  1. 机器人学会对自己下手了,螺丝松了自己拧
  2. python类中方法调用自己类的方法_python怎么调用类方法
  3. C#将WebBowser控件替换为Chrome内核
  4. Linux查看线程的方法小结
  5. linux模拟器使用教程,Ubuntu多机种游戏模拟器Mednafen教程
  6. android 开发按键精灵,安卓按键精灵实现后台
  7. CenOS 6.0 安装NVIDIA GeFore GT 440 显卡驱动
  8. 【Derivation】 条件数学期望公式
  9. Codeforces:F - Elongated Matrix
  10. 清华校友、香港科技大学准博士ICCV顶会论文被爆公然抄袭!去年CVPR也是抄的...
  11. js base64 php,php中的base64decode 与js中的互相转换
  12. PifPaf: Composite Fields for Human Pose Estimation
  13. 基于变色龙认证树的云边端协同流式数据完整性验证模型
  14. 玩法专利获批,发布4年《Beat Saber》为何持续火爆
  15. redis常用命令getex_Redis常用命令整理
  16. WinAPI入门: 第一个标准Win32窗口程序 [改进详细注释版]
  17. T字形路口小车如何要c语言编程,一点通驾校模拟考试
  18. RPG的地牢猎手(优先队列广搜)
  19. 测试开发该如何在团队中推广新工具、新技术(深度好文)
  20. Labview串口通讯驱动包

热门文章

  1. c语言实现图片拼接(linux)
  2. springboot做代理分发服务+代理鉴权
  3. 解决Win7更新时返回0x8024402f错误问题
  4. java cookie过期_Java中Servlet Cookie设置过期时间(expires,max-age)
  5. MySQL双主结构优缺点
  6. 20200123_导航电子地图道路网络分层原理_研讨会视频
  7. 效率最高的Excel数据导入---(c#调用SSIS Package将数据库数据导入到Excel文件中)
  8. easyexcel 导出表格空白问题(有日期字段)
  9. C语言实现设计模式—命令模式
  10. 全面解读商城购物app开发的开发市场现状