Vue响应式原理底层代码模拟实现
整体分析Vue的基本结构如下图所示:(备注:完整代码github地址https://github.com/1512955040/MiniVue)

上图中,为我们模拟最小vue的整体结构,首先创建一个vue类型,它负责把data中的成员注入到vue实例中,并且转化成getter/setter,observer的作用是数据劫持,对data中的属性进行数据监听,如果数据发生变化会获取到最新的值,并通知dep。Compiler的作用是解析每个元素中的指令和差值表达式并替换成相应的数据。Dep的作用是添加观察者,当数据发生变化时通知所有的观察者。Watcher内部有一个Update方法负责更新视图,下面我们用代码的方式一一进行实现。
1.Vue.js功能:
1-1负责接收初始化的参数(选项)
1-2负责把data中的属性注入到vue实例,转化成getter/setter
1-3负责调用observer监听data中所有属性的变化
1-4负责调用Compiler解析指令/差值表达式
类图结构如下:

如上图所示:vue类中有三个属性,分别是$options,$el,$data,这三个属性记录构造函数中传过来的参数。_proxyData为vue类中的方法
所以以_开头的成员就是私有成员,这个方法的功能是把data中的属性转化为getter和setter注入到vue实例中。
class Vue{
constructor(options) {
//1.通过属性保存选项中的数据
this.$options = options || {}
this.$data = options.data || {}
this.$el = typeof options.el === 'string' ? document.querySelector(options.el) : options.el
//2.把data中的成员转化为getter和setter,注入到vue实例中
this._proxyData(this.$data)
//3.调用observer对象,监听数据的变化
new Observer(this.$data)
//4.调用compiler对象,解析指令和差值表达式
new Compiler(this)
}
//把Vue的属性转化为getter和setter,注入到Vue实例中
_proxyData(data){
//遍历data中所有属性
Object.keys(data).forEach(key=>{
//把data的属性注入到vue实例全局中
Object.defineProperty(this,key,{
enumerable:true,
configurable:true,
get(){
return data[key]
},
set(newValue){
if(newValue===data[key]){
return
}
data[key]=newValue
}
})
})
}
}
2.Observer.js功能(数据劫持):
2-1 负责把data选项中的属性转化为响应式数据
2-2 data中的某个属性也是对象,把该属性转化为响应式数据
2-3 数据变化发送通知
类图结构如下:

如上图所示:
walk方法的作用是遍历data中的所有属性,defineReactive是定义响应式数据,也就是通过调用defineReactive方法把属性转化为getter和setter。
class Observer{
constructor(data) {
this.walk(data)
}
//walk方法遍历data中的所有属性
walk(data) {
//1.判断data是否对象
if(!data || typeof data !=='object'){
return
}
//2.遍历data对象的所有属性
Object.keys(data).forEach(key=>{
this.defineReactive(data,key,data[key])
})
}
//degineReactivce方法定义响应式数据 把属性转化为getter和setter
defineReactive(obj,key,val) {
let that=this
// 负责收集依赖,并发送通知
let dep=new Dep()
//如果val传入对象的话也给对象里面的属性添加getter和setter方法
this.walk(val)
Object.defineProperty(obj,key,{
enumerable:true,
configurable:true,
get(){
// 收集依赖
Dep.target && dep.addSub(Dep.target)
return val
},
set(newValue){
if(newValue==val){
return
}
val=newValue
//如果给属性重新赋值成对象,给对象里面的属性重新添加getter和setter方法
//比如:历史数据vm.msg="Hello World" 修改之后vm.msg={a:'Hwllo World'}
//再次调用此方法给vm.msg.a重新添加getter和setter方法
that.walk(newValue)
//发送通知
dep.notify()
}
})
}
}
3.Compiler.js功能:
3-1 负责编译模板,解析指令/差值表达式
3-2 负责页面的首次渲染
3-3 当数据变化后重新渲染视图
类图结构如下:

如上图所示:
el为构造函数传过来的options.el,vm是vue的实例,下面都是vm的方法,对DOM进行操作。compile方法内部遍历dom对象的所有节点,并且
判断这些节点是文本节点,如果是文本节点解析差值表达式,如果是元素节点解析指令,isTextNode和isElementNode方法判断是文本节点还
是元素节点。compileElement和compileText方法解析差值表达式和指令。isDirective这个方法判断元素属性是否是指令。
4.Dep.js功能:
4-1 收集依赖,添加观察者(watcher)
4-2 通知所有观察者

如上图所示:
在vue的响应式机制中,使用观察者模式来响应数据的变化,Dep的作用是收集依赖,在getter方法中收集依赖,在setter方法中通知依赖,每
一个响应式的属性都会场景一个Dep对象,负责收集所有依赖于该属性的地方,所有依赖于该属性的位置都会创建一个watcher对象,所以
Dep就是收集于该属性的watcher对象,使用setter方法去通知依赖,当属性发生变化时调用nodify方法去发送通知,然后调用watcher对象
的update方法。
类的机构如下图:

如上图所示:
subs是一个数组,存储dep中所有的watcher,addSub方法添加watcher,notify方法发布通知
class Dep{
constructor() {
//存储所有的观察者
this.subs=[]
}
// 添加观察者
addSub(sub){
if(sub && sub.update) {
this.subs.push(sub)
}
}
//发送通知
notify(){
this.subs.forEach(sub =>{
sub.update()
})
}
}
5.Watcher.js功能:
5-1 当数据变化触发依赖,dep通知所有的Watcher实例更新视图
5-2 自身实例化的时候往dep对象中添加自己

如上图所示:
data中的每一个属性都要创建一个Dep对象, 在收集依赖的时候把所有对象的watcher添加到dep对象的subs数组中,在setter对象中发送通
知,调用Dep对象的notify方法通知所有关联的watcher对象更新视图。
类图结构如下:

如上图所示:
update对象更新视图,cb回调函数,指明如何更新视图。在更新视图的时候需要一个属性key(data中的属性名称),oldvalue是key 对应的值。
class Watcher{
constructor(vm,key,cb) {
this.vm=vm
//data中的属性名称
this.key=key
//回调函数负责更新视图
this.cb=cb
//把watcher对象记录到Dep类的静态属性target
Dep.target =this
//触发get方法,在get方法中会调用addSub
this.oldValue=vm[key]
Dep.target=null
}
//当数据发生变化时更新视图
update(){
let newValue=this.vm[this.key]
if(this.oldValue === newValue){
return
}
this.cb(newValue)
}
}
下面通过这张图作整体流程的总结:

Vue响应式原理底层代码模拟实现的更多相关文章
- 详解Vue响应式原理
摘要: 搞懂Vue响应式原理! 作者:浪里行舟 原文:深入浅出Vue响应式原理 Fundebug经授权转载,版权归原作者所有. 前言 Vue 最独特的特性之一,是其非侵入性的响应式系统.数据模型仅仅是 ...
- 浅谈vue响应式原理及发布订阅模式和观察者模式
一.Vue响应式原理 首先要了解几个概念: 数据响应式:数据模型仅仅是普通的Javascript对象,而我们修改数据时,视图会进行更新,避免了繁琐的DOM操作,提高开发效率. 双向绑定:数据改变,视图 ...
- 深度解析 Vue 响应式原理
深度解析 Vue 响应式原理 该文章内容节选自团队的开源项目 InterviewMap.项目目前内容包含了 JS.网络.浏览器相关.性能优化.安全.框架.Git.数据结构.算法等内容,无论是基础还是进 ...
- Vue源码--解读vue响应式原理
原文链接:https://geniuspeng.github.io/2018/01/05/vue-reactivity/ Vue的官方说明里有深入响应式原理这一节.在此官方也提到过: 当你把一个普通的 ...
- vue响应式原理,去掉优化,只看核心
Vue响应式原理 作为写业务的码农,几乎不必知道原理.但是当你去找工作的时候,可是需要造原子弹的,什么都得知道一些才行.所以找工作之前可以先复习下,只要是关于vue的,必定会问响应式原理. 核心: / ...
- 深入Vue响应式原理
深入Vue.js响应式原理 一.创建一个Vue应用 new Vue({ data() { return { name: 'yjh', }; }, router, store, render: h =& ...
- vue响应式原理解析
# Vue响应式原理解析 首先定义了四个核心的js文件 - 1. observer.js 观察者函数,用来设置data的get和set函数,并且把watcher存放在dep中 - 2. watcher ...
- 深入解析vue响应式原理
摘要:本文主要通过结合vue官方文档及源码,对vue响应式原理进行深入分析. 1.定义 作为vue最独特的特性,响应式可以说是vue的灵魂了,表面上看就是数据发生变化后,对应的界面会重新渲染,那么响应 ...
- 浅析Vue响应式原理(三)
Vue响应式原理之defineReactive defineReactive 不论如何,最终响应式数据都要通过defineReactive来实现,实际要借助ES5新增的Object.definePro ...
随机推荐
- POJ 2528 Mayor's posters 贴海报 线段树 区间更新
注意离散化!!!线段树的叶子结点代表的是一段!!! 给出下面两个简单的例子应该能体现普通离散化的缺陷: 1-10 1-4 5-10 1-10 1-4 6-10 普通离散化算出来的结果都会是2,但是第二 ...
- CRM企业管理系统一年多少钱?
CRM系统一年多少钱?这是很多企业管理者比较关心的问题.目前市面上的CRM系统分为本地部署型和云部署型.云部署型CRM费用相对较低,只需要按需购买账号,连接网络即可使用:本地部署型CRM费用较高,企业 ...
- gitlab 设置tag保护及取消tag保护功能
用gitlab管理员登录系统 进入项目->设置->Repository 设置项目的Tag保护 效果展示 取消Tag保护 效果展示
- rabbitmq概念简介
AMQP协议 AMQP: Advanced Message Queue,高级队列协议. 特征: 这是一个在进程间传递异步消息的网络协议,因此数据的发送方.接收方以及容器(MQ)都可以在不同的设备上. ...
- Linux学习之路第四天(运行级别)
linux 实用指令 指定运行级别 运行级别说明 0 :关机 1:单用户(找回丢失密码) 2.多用户状态没有网络服务 3.多用户状态有网络服务 4.系统未保留给用户 5.图形界面 6.系统重启 常用的 ...
- 小程序textarea设置maxlength后不是你想的那样简单
可能很多小伙伴们.看见这个标题后; 觉得作者是一个标题党. textarea设置maxlength后, 限制用户输入的字符呗! 还能怎么样呢? 恭喜你,说对了一半. 之前我也一直是这样想的. 知道今天 ...
- String、StringBuilder和StringBuffer的比较
目录 1.String特性 1.1 不可变 1.2 字符串常量池 2.StringBuilder和StringBuffer 2.1 区别 2.2 应用场景 1.String特性 1.1 不可变 它是I ...
- FTP服务—三种登录类型的配置方法
目录 一.部署 二.配置vsftpd 1.匿名用户登录配置 2.系统用户登录配置 3.虚拟用户登录配置 1. 创建虚拟用户名单文件 2. 生成虚拟用户口令认证文件 3. 创建FTP根目录及虚拟用户映射 ...
- Ubuntu中Docker的安装与使用
Ubuntu中安装Docker 更新ubuntu的apt源索引 sudo apt-get update 2.安装包允许apt通过HTTPS使用仓库 sudo apt-get install \ apt ...
- 一、Java预科学习
1.1.什么是计算机 计算机(computer)俗称电脑,是现代一种用于高速计算的电子计算机器,可以进行数值计算,又可以进行逻辑计算,还具有存储记忆功能.是能够按照程序运行,自动.高速处理海量数据的现 ...