《深入浅出vue.js》阅读笔记之数组变化侦测
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 : copyAugment
augment(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的属性中。

《深入浅出vue.js》阅读笔记之数组变化侦测的更多相关文章
- vue.js 学习笔记3——TypeScript
目录 vue.js 学习笔记3--TypeScript 工具 基础类型 数组 元组 枚举 字面量 接口 类类型 类类型要素 函数 函数参数 this对象和类型 重载 迭代器 Symbol.iterat ...
- Vue.js学习笔记(2)vue-router
vue中vue-router的使用:
- Vue.js学习笔记:在元素 和 template 中使用 v-if 指令
f 指令 语法比较简单,直接上代码: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " ...
- Vue中Object和Array数据变化侦测原理
在学完Vue.js框架,完成了一个SPA项目后,一直想抽时间找本讲解Vue.js内部实现原理的书来看看,经过多方打听之后,我最后选择了<深入浅出Vue.js>这本书.然而惭愧的是,这本书已 ...
- 手牵手,从零学习Vue源码 系列二(变化侦测篇)
系列文章: 手牵手,从零学习Vue源码 系列一(前言-目录篇) 手牵手,从零学习Vue源码 系列二(变化侦测篇) 陆续更新中... 预计八月中旬更新完毕. 1 概述 Vue最大的特点之一就是数据驱动视 ...
- 《深入浅出vue.js》阅读笔记之(object)变化侦测
1.什么是变化侦测? 通常,在运行时应用内部的状态会不断发生变化,此时需要不停地重新渲染页面,这时如何确定状态中发生了什么变化? 变化侦测就是用来解决这个问题的,它分为两种类型,一种是"推& ...
- Vue.js——学习笔记
Vue-自学笔记 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅 ...
- Vue.js 学习笔记 第5章 内置指令
本篇目录: 5.1 基本指令 5.2 条件渲染指令 5.3 列表渲染指令 v-for 5.4 方法与事件 5.5 实战:利用计算属性.指令等知识开发购物车 回顾一下第2.2节,我们己经介绍过指令(Di ...
- Vue.js 学习笔记 第4章 v-bind 及 class与style绑定
本篇目录: 4.1 了解v-bind指令 4.2 绑定class的几种方式 4.3 绑定内联样式 DOM元素经常会动态地绑定一些class类名或style样式,本章将介绍使用v-bind指令来绑定cl ...
随机推荐
- Python实现 利用朴素贝叶斯模型(NBC)进行问句意图分类
目录 朴素贝叶斯分类(NBC) 程序简介 分类流程 字典(dict)构造:用于jieba分词和槽值替换 数据集构建 代码分析 另外:点击右下角魔法阵上的[显示目录],可以导航~~ 朴素贝叶斯分类(NB ...
- Python单元测试框架unittest之单用例管理(二)
概述 利用python进行测试时,测试用例的加载方式有2种: 一种是通过unittest.main()来启动所需测试的测试模块,上篇文章就是使用的这种方式: 一种是添加到testsuite集合中再加载 ...
- vscode搭建python环境
这两天刚下了一个pycharm,结果使用之后将vscode给崩了,重装的时候有些步骤也记不清,走了一些弯路,做个总结来记录一下(本人觉得vscode比pycharm好用一点). Python下载安装 ...
- shell脚本(6)-shell数组
一.数组介绍 一个变量只能存一个值,现实中很多值需要存储,可以定义数组来存储一类的值. 二.基本数组 1.概念: 数组可以让用户一次性赋予多个值,需要读取数据时只需通过索引调用就可以方便读出. 2. ...
- Qt开源作品38-无边框窗体方案(无抖动,支持win、linux、mac等系统,侧边半屏顶部全屏)
一 前言 不知道各位程序员有没有遇到过这样一种困惑,好不容易在开源网站找到了类似的想要的项目代码,结果down下来一编译,我勒个去,几百个错误,根本没法用,熟悉的人还好可以直接阅读代码进行修改(有些只 ...
- Mysql 基础用法
#创建表 CREATE TABLE table_name (column_name int) CREATE TABLE IF NOT EXISTS `runoob_tbl`( `runoob_id` ...
- Nodejs 处理异步(获取异步数据并处理)的方法
方法1. 回调函数方式 将异步方法如readFile封装到一个自定义函数中,通过将异步方法得到的结果传给自定义方法的回调函数参数.具体如下(以fs模块的readFile方法为例): //封装 var ...
- C++第三十八篇 -- 研究一下Windows驱动开发(二)--WDM式驱动的加载
基于Windows驱动开发技术详解这本书 一.简单的INF文件剖析 INF文件是一个文本文件,由若干个节(Section)组成.每个节的名称用一个方括号指示,紧接着方括号后面的就是节内容.每一行就是一 ...
- 又一本springmvc学习指南 之---第22篇 springmvc 加载.xml文件的bean标签的过程
writedby 张艳涛,今天看spring mvc 学习指南的第2章,特意提下这个作者是how tomcat works 俩个作者之一, 喜欢上一本书的风格,使用案例来讲述原理, 在做第一个案例的时 ...
- salesforce Integration 概览(一) 杂篇
本篇参考:https://resources.docs.salesforce.com/sfdc/pdf/integration_patterns_and_practices.pdf 我们在做sales ...