vue.js响应式原理解析与实现
vue.js响应式原理解析与实现
从很久之前就已经接触过了angularjs了,当时就已经了解到,angularjs是通过脏检查来实现数据监测以及页面更新渲染。之后,再接触了vue.js,当时也一度很好奇vue.js是如何监测数据更新并且重新渲染页面。今天,就我们就来一步步解析vue.js响应式的原理,并且来实现一个简单的demo。
首先,先让我们来了解一些基础知识。
基础知识
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('fu值操作')
val = newVal
}
})
console.log(obj.name)
obj.name = 'zfj'
console.log(obj.name)
我们通过Object.defineProperty劫持了obj[name]的取值和赋值操作,因此我们就可以在这里做一些手脚啦,比如说,我们可以在obj[name]被赋值的时候触发更新页面操作。
发布订阅模式
发布订阅模式是设计模式中比较常见的一种,其中有两个角色:发布者和订阅者。多个订阅者可以向同一发布者订阅一个事件,当事件发生的时候,发布者通知所有订阅该事件的订阅者。我们来看一个例子了解下。
class Dep {
constructor () {
this.subs = [];
};
//添加订阅
addSub (sub) {
debugger
if(this.subs.indexOf(sub) < 0) {
this.subs.push (sub)
}
};
//通知订阅者
notify () {
this.subs.forEach((subs)=>{
sub.updata();
})
};
};
const dep = new Dep();
const sub = {
updata () {
console.log('sub1 updata');
}
};
const sub1 = {
updata () {
console.log('sub2 updata');
}
};
dep.addSub(sub);
dep.addSub(sub1);
dep.notify();
动手实践
我们了解了Object.defineProperty和发布订阅者模式后,我们不难可以想到,vue.js是基于以上两者来实现数据监听的。
vue.js首先通过Object.defineProperty来对要监听的数据进行getter和setter劫持,当数据的属性被赋值/取值的时候,vue.js就可以察觉到并做相应的处理。
通过订阅发布模式,我们可以为对象的每个属性都创建一个发布者,当有其他订阅者依赖于这个属性的时候,则将订阅者加入到发布者的队列中。利用Object.defineProperty的数据劫持,在属性的setter调用的时候,该属性的发布者通知所有订阅者更新内容。
接下来,我们来动手实现(详情可以看注释):
//实践检测一组数据
let data = {
name: 'cba',
obj:{
age:123
}
}
//定义观察者服务
class observer {
constructor(){
if(!data || typeof data !== 'object') {
return
}
this.data = data
this.walk()
}
//对传入数据进行劫持
walk(){
for(let key in this.data){
this.defineRactive(this.data, key, this.data[key])
}
}
//为属性注册发布者
defineRactive(obj,key,val){
//定义发布者
let dep = new Dep()
//如果属性值为Object继续劫持,层层递归
new observer(val) Object.defineProperty(obj,key,{
get(){
if(Dep.target){
dep.addSub(Dep.target)
}
return val
},
set(newVal){
if(val === newVal){
return
}
new observer(newVal)
dep.notify()
}
})
}
} class Dep {
constructor(){
this.subs = []
}
addSub(sub){
if(this.subs.indexOf(sub) < 0){
this.subs.push(sub)
}
}
notify(){
this.subs.forEach((sub)=>{
sub.upadta()
})
}
}
Dep.target = null
class watch {
constructor(vm, key, updataCb){
this.vm = vm
this.key = key
this.updataCb = updataCb
this.value = null
this.get()
}
get(){
Dep.target = this
let keys = this.keys.split('.')
let value = this.vm
keys.forEach((_key)=>{
value = value[_key]
})
this.value = value
Dep.target = null
return this.value
}
updata(){
let oldValue = this.value
let newValue = this.get()
this.updataCb(oldValue,newValue)
}
} new observer(data)
new watch(data,'name',(a,b)=>{
console.log(a,b)
})
vue.js响应式原理解析与实现的更多相关文章
- vue.js响应式原理解析与实现—实现v-model与{{}}指令
上一节我们已经分析了vue.js是通过Object.defineProperty以及发布订阅模式来进行数据劫持和监听,并且实现了一个简单的demo.今天,我们就基于上一节的代码,来实现一个MVVM类, ...
- 深入解析vue.js响应式原理与实现
vue.js响应式原理解析与实现.angularjs是通过脏检查来实现数据监测以及页面更新渲染.之后,再接触了vue.js,当时也一度很好奇vue.js是如何监测数据更新并且重新渲染页面.vue.js ...
- Vue.js响应式原理
写在前面 因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出. 文章的原地址:answershuto/learnV ...
- Vue.js 响应式原理
1. Vue2.x 基于 Object.defineProperty 方法实现响应式(Vue3 将采用 Proxy) Object.defineProperty(obj, prop, descript ...
- vue响应式原理解析
# Vue响应式原理解析 首先定义了四个核心的js文件 - 1. observer.js 观察者函数,用来设置data的get和set函数,并且把watcher存放在dep中 - 2. watcher ...
- 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 ...
随机推荐
- Sqoop简介
一 Sqoop是什么 Sqoop:SQL-to-Hadoop 连接传统关系型数据库和Hadoop的桥梁 把关系型数据库的数据导入到 Hadoop 系统 ( 如 HDFS.HBase 和 Hive) ...
- 名字top500字典 各种格式及python脚本
原文件名字top500 链接: https://pan.baidu.com/s/1cv0jPYb1-EBceoZz3QNvgg 密码: bat5 中文名字 链接: https://pan.baidu. ...
- ubuntu 主题和zsh终端
ubuntu 主题和zsh终端 1) sudo apt-get install unity-tweak-tool sudo add-apt-repository ppa:noobslab/theme ...
- java8_api_xml
xml处理-1 解析xml的两种方式 DOM主要接口介绍 使用DOM解析XML 解析(parse)是指读入一个文件,确认其有正确的格式,然后将其分解成各种元素,使开发者 ...
- tomcat 常用命令 网上找的资料
打开终端 cd /java/tomcat #执行 bin/startup.sh #启动tomcat bin/shutdown.sh #停止tomcat tail -f logs/catalina.ou ...
- devexpress gridview代码设置
39 //绑定DataTable 40 gridControl1.DataSource = dt; 41 gridView1.OptionsCustomization.AllowColumnMovin ...
- 检查MySQL内存使用情况
==================================================================================================== ...
- streamsets
streamstes用户指南: https://streamsets.com/documentation/datacollector/latest/help/index.html#datacollec ...
- docker 快速部署ES集群 spark集群
1) 拉下来 ES集群 spark集群 两套快速部署环境, 并只用docker跑起来,并保存到私库. 2)弄清楚怎么样打包 linux镜像(或者说制作). 3)试着改一下,让它们跑在集群里面. 4) ...
- ssh登录原理及免密登录配置
ssh登录原理参考: https://www.cnblogs.com/hukey/p/6248468.html ssh登录有两种方式: 1):用户名密码登录 2):基于秘钥的登录 ssh免密登录指的就 ...