1、如何追踪变化

数组的侦测方式和对象不同,比如:

this.list.push(1)

此时并不会像改变对象一样触发setter。

同理,要侦测数组的变化意味着我们在改变数组的时候得到通知,如图,我们可以用一个拦截器覆盖Array.prototype,每当使用array原型方法时,实际

执行的是拦截器中的方法,而拦截器中的方法储存原生方法实现。

2、实现拦截器

拦截器其实是一个和Array.prototype一样的object,只不过这个object中某些可以改变数组自身内容的方法是处理过的。

改变数组内容的方法一共有七个,push,pop,shift, unshiftj, slice, sort 和reverse

const arrayProto = Array.prototype
const arrayMethods = Object.create(arrayProto)
const methods = ['pop', 'push', 'shift', 'unshift', 'splice', 'sort', 'reverse']
methods.forEach(function (method) {// 缓存原始方法const original = arrayProto[method]Object.defineProperty(arrayMethods, method, {value: function mutator (...args) {return original.apply(this, args)},enumerable: false,writable: true,configurable: true,})
})

上面代码中,arrayMethods继承自Array.prototype,具备其所有功能。当使用push方法时,调用的是arrayMethods.push,即mutator函数,这里可以做一些发送通知

变化之类的事情。

3、使用拦截器覆盖Array原型

有了拦截器,就需要让它覆盖Array.prototype,但又不能直接覆盖,因为会污染全局变量Array,我们希望只是拦截那些被侦测了变化的数据生效。

这时就需要借助Observer

class Observer {constructor (value) {this.value = value}if (Array.isArray(value)) {value.__proto__ = arrayMethods} else {this.walk(value)}
}

它的作用是将拦截器(加工后具备拦截功能的arrayMethods)赋值给value.__proto__,通过__proto__巧妙的实现覆盖value原型功能。

__proto__其实是Object.getPrototypeOf和Object.setPrototypeOf的早期实现,所以使用es6的Object.setPrototypeOf来代替__ptoto__可以实现同样的效果。

4、将拦截器方法挂载到数组属性上

虽然绝大多数浏览器都支持这个非标准的属性来访问原型,但并不是所有浏览器都支持,因此需要处理不能使用__proto__的情况。

vue的做法是对于不能使用__proto__的,直接将arrayMethods身上的这些方法设置到被侦测的数组上。

export class Object {if (Array.isArray(value)) {const augment = hasProto ? protoAugment : copyAugmentaugment(value, arrayMethods, arrayKeys)} else {this.walk(value)}
}function protoAugment (target, src, keys) {target.__proto__ = src
}function copyAugment (target, src, keys) {for (let i=0, len = keys.lenght;i< 1; i++) {const key = keys[i]default(target, key, src[key])}
}

在上面代码中,新增了hasProto来判断当前浏览器是否支持__proto__,如果支持,则使用protoAugment覆盖原型,否则用copyAugment将拦截器中的方法挂载到value。

copyAugment函数用来将已经加工了拦截操作的原型方法直接添加到value的属性中。

转载于:https://www.cnblogs.com/pjl43/p/10666448.html

《深入浅出vue.js》阅读笔记之数组变化侦测相关推荐

  1. 深入浅出Vue.js阅读——整体流程——实例方法与全局API的实现原理

    深入浅出Vue.js阅读--整体流程--实例方法与全局API的实现原理 1. 数据相关的实例方法 2. 事件相关的实例方法 1. vm.$on 2. vm.$off 3. vm.$once 4. vm ...

  2. 畅销书《深入浅出Vue.js》作者,在阿里淘系1年的收获成长

    大家好,我是若川.今天推荐一篇95年的博文的文章.他的故事应该挺多人知道.如果不知道可以看他的博客 https://github.com/berwin/blog 点击下方卡片关注我.加个星标 时间好快 ...

  3. Vue.js 学习笔记 八 v-for

    v-for指令,是用来循环的,常用的情况有以下4种 <div id="divApp"><!--迭代数字--><p v-for="n in 5 ...

  4. Vue.js学习笔记 2022 04 17

    Vue.js学习笔记 1 Vue.js基础 Vue.js介绍 vuejs 渐进式 JavaScript 框架 Vue.js 如何应用 1 在普通html项目中,引入VUE.JS Hb 的项目 生成的 ...

  5. Vue.js 学习笔记 七 控制样式

    Vue.js可以灵活的控制样式 我们首先随便写2个样式 <style>.divCss {background-color: green;width:400px;height:400px;} ...

  6. Vue.js 学习笔记 六 v-model 双向绑定数据

    之前说的v-bind指令,可以绑定数据,但是是单向的,从model向view绑定,下面介绍v-model,可以双向绑定数据 <div id="divApp"><p ...

  7. Vue.js 学习笔记 一

    上手前的一些概念 为啥要用Vue.js Vue.js 是目前最流行的前端框架之一,专注于视图层,容易上手. 使用Vue.js,通过框架提供的指令可以减少很多DOM操作(数据的双向绑定),提高渲染效率, ...

  8. 遇见 vue.js --------阿文的vue.js学习笔记(8 —1)------- 列表渲染

    ** 新学习新征程,我们一起踏上学习 vue.js的新长征 遇见 vue.js --------阿文的vue.js学习笔记(1)-----初识vue.js 遇见 vue.js --------阿文的v ...

  9. 畅销书《深入浅出Vue.js》作者,在阿里淘系6个月的收获成长

    本文作者:刘博文(Berwin),花名"玖五",畅销书<深入浅出Vue.js>作者.知名技术博主.讲师.阿里巴巴淘系技术部前端技术专家,现负责淘系618.双11等超大型 ...

最新文章

  1. DFS Codeforces Round #299 (Div. 2) B. Tavas and SaDDas
  2. 世界首台!我国量子计算机超越早期经典计算机
  3. [SpringSecurity]基本原理_两个重要的接口_UserDetailsService接口和PasswordEncoder接口
  4. 2019-03-15-算法-进化(两数之和)
  5. 一种基于伪标签半监督学习的小样本调制识别算法
  6. 06512oracle数据库,ORA-06512 – 专业Oracle数据库恢复,或许是您恢复数据的最后机会@phone:13429648788 - 专业Oracle数据库恢复技术支持...
  7. Django上传文件,制作文件上传按钮,form上传文件
  8. delphi 中如果不进行 closehandle 会怎么样_报考八一农大的十一大选择之七|带你走进不一样的“信息世界”...
  9. Exceeded maximum number of retries. Exceeded max scheduling attempts 3 for instance
  10. 云计算实战系列十三(Linux计划任务)
  11. java输入一个字符给c赋值_C语言字符串的输入输出
  12. Centos7 Kubernetes(k8s) 开发服务器(单服务器)部署nacos-sentinel-rocketmq-zipkin-elasticsearch等等 一键部署 即开即用服务
  13. php7 imagick扩展,php7如何安装imagick扩展
  14. 软件测试工程师必备技能之Java基础
  15. 在线ps,修改证件照背景色
  16. 脱壳之aspack压缩壳
  17. 从理论到实战-如何理解那个把嫦娥送上天的卡尔曼滤波算法Kalman filter?
  18. MapReduce处理两个文件内不同行信息
  19. SpringBoot+Vue项目实现高校学生健康打卡系统
  20. 「今日 GitHub 趋势」让全世界程序员体会中国的 12306 抢票狂潮

热门文章

  1. linux module_init
  2. CTF 这个看起来有点简单
  3. mongodb python 大于_Python中使用MongoDB详解
  4. l380废墨收集垫已到使用寿命_湖北雨水收集系统定制
  5. 使用express搭建服务器获取MySQL数据库数据
  6. LeetCode 2131. 连接两字母单词得到的最长回文串
  7. LintCode 1915. 举重(01背包)
  8. LeetCode 469. 凸多边形(向量叉积)
  9. LeetCode 835. 图像重叠
  10. 剑指Offer - 面试题6. 从尾到头打印链表(栈,递归,反转链表)