《深入浅出vue.js》阅读笔记之(object)变化侦测
1、什么是变化侦测?
通常,在运行时应用内部的状态会不断发生变化,此时需要不停地重新渲染页面,这时如何确定状态中发生了什么变化?
变化侦测就是用来解决这个问题的,它分为两种类型,一种是“推”(push),另一种是拉(pull)。
angular和react的变化侦测属于“拉”,即当状态发生变化时,它不知道那个状态变了,只知道状态可能变了,然后会发送一个信号通知框架,框架内部收到信号后,就会进行对比找出哪些dom需要重新渲染,在angular中称为脏检查,在react中则使用虚拟dom。
而vue框架的变化侦测属于“推”。当状态发生变化时,vue立刻就知道了,而且在一定程度上知道哪些状态变了。因此,它知道的信息更多,也就可以进行更细粒度的更新。
所谓细粒度的更新,也就是说,假如一个状态绑定了好几个依赖,每个依赖表示一个具体的dom节点,那么当这个状态发生变化时,向这个状态的所有依赖发送通知进行dom更新操作,也可以看出“拉”的粒度是最粗的。
2、如何追踪变化?
两种方法,Object.defineProperty和es6的Proxy。由于es6在浏览器中的支持度并不理想,所以vue使用的是第一种。
知道了Object.defineProperty可以侦测对象的变化,那就可以写出以下的代码:
function defineReactive (data, key, val) {
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get: function () {
return val
},
set: function (newval) {
if (val === newval) {
return
}
val = newval
}
})
}
该函数作用是定义一个响应式数据,也就是在这个函数中进行追踪变化,当从data的key中读取数据时,get函数被触发;当从data的key中设置数据时,set函数被触发。
3、如何收集依赖?
我们之所以要观察数据,目的是当数据的属性发生变化时,可以通知那些曾经使用了该数据的地方。
例如:
<template>
<h1>{{name}}</h1>
</template>
该模版中使用了name,当它发生变化时,要向使用了它的地方发送通知。
实现的方法是,把用到数据name的地方收集起来,然后属性发生变化时,把之前收集好的依赖循环触发一遍。也就是在getter中收集依赖,setter中触发依赖。
4、依赖收集在哪里?
首先想到的是每个key都有一个数组,用来存储当前key的依赖。假设依赖是一个函数,保存在window.target上,现在可以把上面的defineReactive函数改造下:
function defineReactive (data, key, val) {
let dep = [] //new
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get: function () {
dep.push(window.target)
return val
},
set: function (newval) {
if (val === newval) {
return
}
// new
for (let i=0;i<dep.length;i++) {
dep[i](newval, val)
}
val = newval
}
})
}
这里新增了数组dep,用来存储被收集的依赖,然后在set被触发时,循环dep以触发收集到的依赖。
这里可以专门封装一个帮助我们管理依赖的类,用来收集、删除和发送通知的类:
export default class dep {
constructor () {
this.subs = []
}
addSub (sub) {
this.subs.push(sub)
}
removeSub (sub) {
remove(this.sub, sub)
}
depend () {
if (window.target) {
this.addSub(window.target)
}
}
notify () {
const subs = this.subs.slice()
for (let i=0,l = subs.length;i<1;i++) {
subs[i].update()
}
}
}
function remove (arr, item) {
if (arr.length) {
const index = arr.indexOf(item)
if (index > -1) {
return arr.splice(index, 1)
}
}
}
再改造下之前的函数:
function defineReactive (data, key, val) {
let dep = new dep() //update
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get: function () {
dep.depend()
return val
},
set: function (newval) {
if (val === newval) {
return
}
val = newval
// new
dep.notify()
}
})
}
这样就清晰很多了
《深入浅出vue.js》阅读笔记之(object)变化侦测的更多相关文章
- 《深入浅出vue.js》阅读笔记之数组变化侦测
1.如何追踪变化 数组的侦测方式和对象不同,比如: this.list.push(1) 此时并不会像改变对象一样触发setter. 同理,要侦测数组的变化意味着我们在改变数组的时候得到通知,如图,我们 ...
- 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" " ...
- JDK1.8源码阅读笔记(1)Object类
JDK1.8源码阅读笔记(1)Object类 Object 类属于 java.lang 包,此包下的所有类在使⽤时⽆需⼿动导⼊,系统会在程序编译期间⾃动 导⼊.Object 类是所有类的基类,当⼀ ...
- 手牵手,从零学习Vue源码 系列二(变化侦测篇)
系列文章: 手牵手,从零学习Vue源码 系列一(前言-目录篇) 手牵手,从零学习Vue源码 系列二(变化侦测篇) 陆续更新中... 预计八月中旬更新完毕. 1 概述 Vue最大的特点之一就是数据驱动视 ...
- Vue.js——学习笔记
Vue-自学笔记 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅 ...
- Vue.js 学习笔记 第4章 v-bind 及 class与style绑定
本篇目录: 4.1 了解v-bind指令 4.2 绑定class的几种方式 4.3 绑定内联样式 DOM元素经常会动态地绑定一些class类名或style样式,本章将介绍使用v-bind指令来绑定cl ...
- Vue.js——学习笔记(一)
Vue-自学笔记 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅 ...
随机推荐
- vmware使用U盘安装系统
创建好系统 创建一个新的硬盘,选择"physicalDrive1" 如果识别不到physicalDrive 1,使用下面的方法. 1.在本机的服务里面启用下面的服务. 2.重启 V ...
- kali2020安装中文界面
1.安装中文字体:apt-get install xfonts-intl-chinese ttf-wqy-microhei 2.设置系统语言:dpkg-reconfigure locales 3.选择 ...
- Luogu P4313 文理分科
link 最小割 双倍经验 这道题运用了最小割最常用的一种用法:集合划分. 因为源汇最小割即就是将源汇划分到不同的集合,那么最简单的应用就是最小代价划分集合了. 本题中,题意是将 \(n\cdot m ...
- 【Python从入门到精通】(十)Python流程控制的关键字该怎么用呢?【收藏下来,常看常新】
您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦. 这篇文章主要介绍Python中流程控制的关键字的使用,涉及到if else,for,while等关键字 干货满满,建议收藏,需要用到时常看看. 小 ...
- C语言:预处理 编译过程分解 证明图
- spring-4-申明事务
categories: spring5 事务回顾 事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎! 事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性. 事务就是把一 ...
- 微信小程序云开发-数据库-更新数据
一.js文件代码使用.update更新数据 写一个更新数据的函数,函数内使用.update更新数据.一定要通过.doc指定修改哪一条数据. 二.wxml文件修改数据的按钮 在wxml文件中写[修改] ...
- 为了让她学画画——熬夜用canvas实现了一个画板
前言 大家好,我是Fly, canvas真是个强大的东西,每天沉迷这个无法自拔, 可以做游戏,可以对图片处理,后面会给大家分享一篇,canvas实现两张图片找不同的功能, 听着是不是挺有意思的, 有点 ...
- [HNOI2008]GT考试 题解
这题比较难搞.考虑设计状态:\(f_{i,j}\) 表示当前考虑到 \(X_i\) 位,且 \(X\) 的后 \(j\) 位刚好与 \(A\) 列匹配时的方案数.最终答案为 \(\sum_{i=0}^ ...
- 【NOIP2007】Hanoi双塔问题
题目描述 给定A.B.C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的(下图为n=3的情形). 现要将这些圆盘移到C柱上 ...