《深入浅出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 的核心库只关注视图层,不仅 ...
随机推荐
- Chirp Z-Transform
Chirp Z-Transform 其实不是什么特别难的东西. 用于解决等比数列/类等比数列多点求值. \(b_i=\sum_{j=0}^{n}a_jc^{ij}\) 注意到 \(ij=\binom{ ...
- python 12篇 mock接口之flask模块
一.使用pip install flask按照flask模块. import flask,json # 轻量级web开发框架 server = flask.Flask(__name__) @serve ...
- POJ 尺取法
poj3061 Subsequence 题目链接: http://poj.org/problem?id=3061 挑战P146.题意:给定长度为n的数列整数a0,a1,...,a(n-1)以及整数S, ...
- Jupyter使用快捷键
命令行模式(按 Esc 生效) F: 查找并且替换 Ctrl-Shift-F: 打开命令配置 Ctrl-Shift-P: 打开命令配置 Enter: 进入编辑模式 P: 打开命令配置 Shift-En ...
- tensorflow2 自定义损失函数使用的隐藏坑
Keras的核心原则是逐步揭示复杂性,可以在保持相应的高级便利性的同时,对操作细节进行更多控制.当我们要自定义fit中的训练算法时,可以重写模型中的train_step方法,然后调用fit来训练模型. ...
- 第四篇 -- Go语言string转其他类型
1. string转int // 法1:string转int num_str := "1234567" /* ParseInt():查看文档https://studygolang. ...
- Pb代理工具之mitmproxy
mitmproxy 一 . mitmproxy介绍 mitmproxy 就是用于 MITM 的 proxy,MITM 即中间人攻击(Man-in-the-middle attack). 不同于 fid ...
- centos7网卡配置文件
HWADDR=00:0c:29:a7:8e:ee TYPE=Ethernet BOOTPROTO=staticDEFROUTE=yes PEERROUTES=yesPEERROUTES=yes IPV ...
- 点云上的深度学习及其在三维场景理解中的应用(PPT内容整理PointNet)
这篇博客主要是整理了PointNet提出者祁芮中台介绍PointNet.PointNet++.Frustum PointNets的PPT内容,内容包括如何将点云进行深度学习,如何设计新型的网络架构 ...
- [WUSTCTF2020]朴实无华
[WUSTCTF2020]朴实无华 考点:1.MD5碰撞 2.命令执行绕过 打开题发现编码有些问题,修改编码为utf-8 看了源码和请求包没发现什么东西,看到title想到了robots.txt文件, ...