深入解析vue.js响应式原理与实现
vue.js响应式原理解析与实现。angularjs是通过脏检查来实现数据监测以及页面更新渲染。之后,再接触了vue.js,当时也一度很好奇vue.js是如何监测数据更新并且重新渲染页面。vue.js响应式原理解析与实现
Object.defineProperty
es5新增了Object.defineProperty这个api,它可以允许我们为对象的属性来设定getter和setter,从而我们可以劫持用户对对象属性的取值和赋值。比如以下代码:
const obj = {
};
let val = 'cjg';
Object.defineProperty(obj, 'name', {
get() {
console.log('劫持了你的取值操作啦');
return val;
},
set(newVal) {
console.log('劫持了你的赋值操作啦');
val = newVal;
}
});
console.log(obj.name);
obj.name = 'cwc';
console.log(obj.name);
//欢迎加入全栈开发交流圈一起学习交流:864305860
我们通过Object.defineProperty劫持了obj[name]的取值和赋值操作,我们可以在obj[name]被赋值的时候触发更新页面操作。
发布订阅模式
当事件发生的时候,发布者通知所有订阅该事件的订阅者。我们来看一个例子了解下。
class Dep {
constructor() {
this.subs = [];
}
// 增加订阅者
addSub(sub) {
if (this.subs.indexOf(sub) < 0) {
this.subs.push(sub);
}
}
// 通知订阅者
notify() {
this.subs.forEach((sub) => {
sub.update();
})
}
}
const dep = new Dep();
const sub = {
update() {
console.log('sub1 update')
}
}
const sub1 = {
update() {
console.log('sub2 update');
}
}
dep.addSub(sub);
dep.addSub(sub1);
dep.notify(); // 通知订阅者事件发生,触发他们的更新函数
全栈开发交流圈:864305860.png
vue.js首先通过Object.defineProperty来对要监听的数据进行getter和setter劫持,当数据的属性被赋值/取值的时候,vue.js就可以察觉到并做相应的处理。
class Observer {
constructor(data) {
// 如果不是对象,则返回
if (!data || typeof data !== 'object') {
return;
}
this.data = data;
this.walk();
}
// 对传入的数据进行数据劫持
walk() {
for (let key in this.data) {
this.defineReactive(this.data, key, this.data[key]);
}
}
// 创建当前属性的一个发布实例,使用Object.defineProperty来对当前属性进行数据劫持。
defineReactive(obj, key, val) {
// 创建当前属性的发布者
const dep = new Dep();
/*
* 递归对子属性的值进行数据劫持,比如说对以下数据
* let data = {
* name: 'cjg',
* obj: {
* name: 'zht',
* age: 22,
* obj: {
* name: 'cjg',
* age: 22,
* }
* },
* };
* 我们先对data最外层的name和obj进行数据劫持,之后再对obj对象的子属性obj.name,obj.age, obj.obj进行数据劫持,层层递归下去,直到所有的数据都完成了数据劫持工作。
*/
new Observer(val);
Object.defineProperty(obj, key, {
get() {
// 若当前有对该属性的依赖项,则将其加入到发布者的订阅者队列里
if (Dep.target) {
dep.addSub(Dep.target);
}
return val;
},
set(newVal) {
if (val === newVal) {
return;
}
val = newVal;
new Observer(newVal);
dep.notify();
}
})
}
}
// 发布者,将依赖该属性的watcher都加入subs数组,当该属性改变的时候,则调用所有依赖该属性的watcher的更新函数,触发更新。
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
if (this.subs.indexOf(sub) < 0) {
this.subs.push(sub);
}
}
notify() {
this.subs.forEach((sub) => {
sub.update();
})
}
}
Dep.target = null;
// 观察者
class Watcher {
/**
*Creates an instance of Watcher.
* @param {*} vm
* @param {*} keys
* @param {*} updateCb
* @memberof Watcher
*/
constructor(vm, keys, updateCb) {
this.vm = vm;
this.keys = keys;
this.updateCb = updateCb;
this.value = null;
this.get();
}
// 根据vm和keys获取到最新的观察值
get() {
Dep.target = this;
const keys = this.keys.split('.');
let value = this.vm;
keys.forEach(_key => {
value = value[_key];
});
this.value = value;
Dep.target www.michenggw.com= null;
return this.value;
}//欢迎加入全栈开发交流圈一起学习交流:864305860
update() {
const oldValue = this.value;
const newValue = this.get();
if (oldValue !== newValue) {
this.updateCb(oldValue, newValue);
}
}
}
let data = {
name: 'cjg',
obj: {
name: 'zht',
},
};
new Observer(data);
// 监听data对象的name属性,当data.name发现变化的时候,触发cb函数
new Watcher(data, 'name', www.gcyl152.com/(oldValue, newValue) => {
console.log(oldValue, newValue);
})
data.name = 'zht';
// 监听data对象的obj.name属性,当data.obj.name发现变化的时候,触发cb函数
new Watcher(data, 'obj.name',www.gcyL157.com (oldValue, www.dfgjpt.com newValue) => {
console.log(oldValue,www.mingcheng178.com newValue);
})
data.obj.name =www.furggw.com 'cwc';
data.obj.name =www.mhylpt.com 'dmh';
这样,一个简单的响应式数据监听就完成了。当然,这个也只是一个简单的demo,来说明vue.js响应式的原理,真实的vue.js源码会更加复杂,因为加了很多其他逻辑。
深入解析vue.js响应式原理与实现的更多相关文章
- vue.js响应式原理解析与实现
vue.js响应式原理解析与实现 从很久之前就已经接触过了angularjs了,当时就已经了解到,angularjs是通过脏检查来实现数据监测以及页面更新渲染.之后,再接触了vue.js,当时也一度很 ...
- Vue.js响应式原理
写在前面 因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出. 文章的原地址:answershuto/learnV ...
- vue.js响应式原理解析与实现—实现v-model与{{}}指令
上一节我们已经分析了vue.js是通过Object.defineProperty以及发布订阅模式来进行数据劫持和监听,并且实现了一个简单的demo.今天,我们就基于上一节的代码,来实现一个MVVM类, ...
- Vue.js 响应式原理
1. Vue2.x 基于 Object.defineProperty 方法实现响应式(Vue3 将采用 Proxy) Object.defineProperty(obj, prop, descript ...
- Vue 源码解析:深入响应式原理(上)
原文链接:http://www.imooc.com/article/14466 Vue.js 最显著的功能就是响应式系统,它是一个典型的 MVVM 框架,模型(Model)只是普通的 JavaScri ...
- vue深入响应式原理
vue深入响应式原理 深入响应式原理 — Vue.jshttps://cn.vuejs.org/v2/guide/reactivity.html 注意:这里说的响应式不是bootsharp那种前端UI ...
- Vue 数据响应式原理
Vue 数据响应式原理 Vue.js 的核心包括一套“响应式系统”.“响应式”,是指当数据改变后,Vue 会通知到使用该数据的代码.例如,视图渲染中使用了数据,数据改变后,视图也会自动更新. 举个简单 ...
- Vue的响应式原理
Vue的响应式原理 一.响应式的底层实现 1.Vue与MVVM Vue是一个 MVVM框架,其各层的对应关系如下 View层:在Vue中是绑定dom对象的HTML ViewModel层:在Vue中是实 ...
- 一探 Vue 数据响应式原理
一探 Vue 数据响应式原理 本文写于 2020 年 8 月 5 日 相信在很多新人第一次使用 Vue 这种框架的时候,就会被其修改数据便自动更新视图的操作所震撼. Vue 的文档中也这么写道: Vu ...
随机推荐
- Java的“Goto”与标签
goto在Java中是一个保留字,但在语言中并没有用到它:Java没有goto.但是,Java也能完成一些类似于跳转的操作,主要是依靠:标签. 为什么要使用标签 在迭代语句中,我们可以使用break和 ...
- 爬虫学习(十一)——bs4基础学习
ba4的介绍: bs4是第三方提供的库,可以将网页生成一个对象,这个网页对象有一些函数和属性,可以快捷的获取网页中的内容和标签 lxml的介绍 lxml是一个文件的解释器,python自带的解释器是: ...
- jstree 全部选中事件 select_all 使用
select_all function of jstree not checked node for jstree-open branch of ajax-jstree 很尴尬啊,找了整个百度,360 ...
- 用 js 写一个获取随机颜色的程序
function getColor(){ var color="#"; for(var i=0;i<6;i++){ color+=(Math.random()*16 | 0) ...
- 图解HTTP总结(6)——HTTP首部
HTTP报文首部 HTTP 协议的请求和响应报文中必定包含 HTTP 首部. 首部内容为客户端和服务器分别处理请求和响应提供所需要的信息. 对于客户端用户来说, 这些信息中的大部分内容都无须亲自查看. ...
- B1005 继续(3n+1)猜想 (25分)
B1005 继续(3n+1)猜想 (25分) 卡拉兹(Callatz)猜想已经在1001中给出了描述.在这个题目里,情况稍微有些复杂. 当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程 ...
- 笔记-scrapy-setting
笔记-scrapy-setting 1. 简介 Scrapy设置允许您自定义所有Scrapy组件的行为,包括核心,扩展,管道和蜘蛛本身. 可以使用不同的机制来填充设置,每种机制都有不同的优先级 ...
- 理解线程3 c语言示例线程基本操作
Table of Contents 1. 基本线程的动作 1.1. 设置线程属性 1.1.1. 设置脱离状态 1.1.2. 设置调度属性 1.2. 取消线程 1.3. 主线程创建多个线程示例 2. 了 ...
- 变量存储类型(auto static extern)
auto 动态存储类型变量(函数内部变量存储默认为 auto型) auto只用于函数内部定义,单片机在执行这个函数时为它分配内存地址,当函数执行完毕返回后,auto变量会被销毁,再次进入这个函数时,它 ...
- ElasticSearch学习笔记(三)-- 查询
1. URISearch详解与演示 2. QueryDSL简介 3. 字段类查询简介及match-query 4. 相关性算分 5. match-phrase-query 6. query-strin ...