博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
vue[源码]之数组处理与拦截变异
阅读量:7053 次
发布时间:2019-06-28

本文共 2416 字,大约阅读时间需要 8 分钟。

先看下拦截数组变异处理的源码:

const arrayProto = Array.prototype //缓存 Array.prototype// 实现 arrayMethods.__proto__ === Array.prototype  //(拷贝了数组原型下的方法)export const arrayMethods = Object.create(arrayProto)const methodsToPatch = [      'push',   //定义了数组所有的变异方法     'pop',       'shift',       'unshift',       'splice',        'sort',        'reverse']/** * Intercept mutating methods and emit events */methodsToPatch.forEach(function (method) {  //遍历数组      // 缓存了数组原本的变异方法      const original = arrayProto[method]  //使用 def 函数在 arrayMethods 对象上定义与数组变异方法同名的函数,从而做到拦截的目的 def(arrayMethods, method, function mutator (...args) {//上定义与数组变异方法同名的函数,在函数体内优先调用了缓存下来的数组变异方法const result = original.apply(this, args)    //定义了 ob 常量,它是 this.__ob__ 的引用       const ob = this.__ob__           let inserted    //定义变量//数组方法对数组的操作       switch (method) {         case 'push':               case 'unshift':                 inserted = args                 break         case 'splice':         inserted = args.slice(2)         break    } //进行观测,达到数组响应式  if (inserted) ob.observeArray(inserted)      // notify change      ob.dep.notify()      return result   //导出arrayMethods对象   })})复制代码

这段源码主要是对数组变异的拦截处理,定义了一个数组储存了数组变异的方法,遍历得到每一个变异方法。添加到数组原型下面 主要是为了防止在某些浏览器没有__proto__的情况下兼容。

可以看下数组变异拦截方法(
Observer类的
constructor 函数 )

const arrayKeys = Object.getOwnPropertyNames(arrayMethods)//获取属性名称(要拦截的数组变异方法名字)复制代码

constructor (value: any) {  this.value = value  this.dep = new Dep()  this.vmCount = 0  def(value, '__ob__', this) //为其定义一个__ob__  if (Array.isArray(value)) {//判断是否为数组    if (hasProto) {//检测是否可用__proto__属性        protoAugment(value, arrayMethods)      } else {        copyAugment(value, arrayMethods, arrayKeys)      }//触发依赖(观察者)观测      this.observeArray(value)  } else {    this.walk(value)  }}复制代码

protoAugment方法(__proto__)可用情况下复制代码

function protoAugment (target, src: Object) {  /* eslint-disable no-proto */  target.__proto__ = src   /* eslint-enable no-proto */}//设置数组实例的 __proto__ 属性,让其指向一个代理原型,从而做到拦截复制代码

copyAugment方法(__proto__)不可用情况下复制代码

function copyAugment (target: Object, src: Object, keys: Array
) { for (let i = 0, l = keys.length; i < l; i++) { const key = keys[i] def(target, key, src[key]) }}//copyAugment 函数的第三个参数 keys 就是定义在 arrayMethods 对象上的所有函数的键,即所有要拦截的数组变异方法的名称。这样通过 for 循环对其进行遍历,并使用 def 函数在数组实例上定义与数组变异方法同名的且不可枚举的函数,这样就实现了拦截操作。(主要为不支持__proto__)做兼容复制代码

转载于:https://juejin.im/post/5ca77792f265da307352dcbd

你可能感兴趣的文章
四则运算 第二次
查看>>
SVN同步
查看>>
python转移符的使用
查看>>
淘宝笔试题,受限的降序打印
查看>>
插入排序与快排
查看>>
8.4(Java学习笔记)java脚本引擎(Rhino)
查看>>
qt终于安装成功
查看>>
通知栏添加手电筒 通知栏常驻 通知栏常在 锁屏黑屏界面手势绘图打开手电筒...
查看>>
TinyXML:一个优秀的C++ XML解析器(转载)
查看>>
字符串匹配算法之KMP&Boyer-Moore
查看>>
iOS WKWebView的使用
查看>>
开始记录 Windows Phone 生涯
查看>>
django中TypeError: __init__() missing 1 required positional argument: 'app_module'
查看>>
C#窗体之-->窗口外观属性...
查看>>
搜索框auto_complete
查看>>
Java之戳中痛点 - (6)避免类型自动转换,例如两个整数相除得浮点数遇坑
查看>>
安装 libmagic in Mac OS (for Python-magic)
查看>>
设置作者信息等设置
查看>>
【OpenGL学习】使用Shader做图像处理
查看>>
subversion linux使用方法
查看>>