[TOC]
****
## 1 Vue的数据绑定
>[info] 数据绑定的实现分为**数据层劫持**与**UI层事件注册**。
>[info] 这里分析vue对数据层劫持的实现机制
## 2 实现observer(数据观察者)
>[info] 对observe对象的属性进程set/get操作劫持
>[info] 实现劫持后对Observer对象属性的set与get操作可以触发响应操作,
>[info] 其中的操作包括UI层的更新与其他数据的刷新
~~~
export default class Observer{
constructor(value){
;属性value获取
this.value = value
;属性遍历
this.walk(value)
}
;遍历操作
walk(value){
;获取属性value的keys
var keys = Object.keys(value)
;遍历keys
keys.foreach(
;将key对应的值转换为劫持属性
key=>this.convert(key,value[key])
)
}
;转换属性为劫持属性
convert(key,val){
defineReactive(this.value,key,val)
}
;属性转换操作
expot function defineReactive(obj,key,val){
;val递归遍历
var childOb = observe(val)
;注册为劫持属性
Object.defineProperty(obj,key,val){
enumerable : true,
configurable : true,
get:() => val,
set:newVal=>{
childOb = observe(newVal)
}
}
}
;属性递归操作
export function observe(value,vm){
if(!value||typeof value ! = 'object'){
return
}
;生成数据监视器observer
return new Observer(value)
}
}
~~~
## 3 实现Dep(消息订阅器)
>[info] set操作会广播消息到订阅器数组的所有订阅者
>[info] 消息订阅器数组的订阅者将会进行刷新操作。
>[info] 消息订阅器中的订阅者可以是UI层也可以是数据层
~~~
;Dep实现
export default class Dep{
constructor(){
this.subs = []
}
addSub(sub){
this.subs.push(sub)
}
notify(){
this.subs.forEach(sub=>sub.update())
}
}
~~~
~~~
;注册Dep(消息订阅器)到observer(数据观察者)
export function defineReactive(obj,key,val){
;创建订阅器数组
var dep = new Dep()
;注册为劫持属性
var childOb = observe(val)
Object.defineProperty(obj,key,{
enumberable:true,
configurable:true,
get:()=>val,
set:newVal =>{
;旧值
var value = val
;比较新旧值
if(newVal === value){
return
}
;值不相等进行处理
val = newVal
childOb = observe(newVal)
;广播数据更新到消息订阅者数组
dep.notify()
}
})
}
~~~
## 4 实现Watcher(消息订阅者)
>[info] 消息订阅者存储在消息订阅器数组中
>[info] 数据层的set操作会广播消息到订阅器数组
>[info] 订阅器数组中的订阅者会进行自我刷新操作
>[info] 消息订阅者可以是数据层也可以是UI层
~~~
;实现消息订阅者
export default class Watcher{
constructor(vm,expOrFn,cb){
this.cb = cb
this.vm = vm
this.expOrFn = expOrFn
this.value = this.get()
}
;消息订阅者刷新操作
update(){
this.run()
}
;刷新运行过程
run(){
const value = this.get()
if( vakue ! == this.value){
this.value = value
this.cb.call(this.vm)
}
}
;获取指令表达式的值
get(){
const value = this.vm._data[this.expOrFn]
return value
}
}
~~~
>[info] 现在需要将消息订阅者注册到消息订阅器中
>[info] 这样数据层set层广播消息到消息订阅器数组
>[info] 消息订阅者可接受消息进行相应刷新操作
>[info] 注册的关键在Object.defineProperty的get()被调用时
>[info] Watcher的get()会调用数据层的get()。
>[info] 触发get劫持,注册Watcher到Dep数组中
>[info] 为了判断是否在Watcher中进行get,需要设置一个状态位
~~~
;修改后的watcher
export default class Watcher{
....
get(){
;设置状态标志
Dep.target = this
;调用Object.defineProperty()注册的get劫持
const value = this.vm._data[this.expOrFn]
;还原状态标识
Dep.target = null
return value
}
....
}
~~~
~~~
;修改后的definReactive()
export function defineReactive(obj,key,val){
;创建消息订阅器数组
var dep = new Dep()
;修改为劫持属性
var childOb = observe(val)
Object.defineProperty(obj,key,{
enumberable : true,
configurable : true,
get:() => {
;检查是否watch的get,注册到Dep中
if(Dep.target){
dep.addSub(Dep.target)
}
return val
},
set:newVal => {
var value = val
;值相等直接返回
if(newVal === value){
return
}
;值不相等触发刷新操作
val = newVal
childOb = observe(newVal)
dep.ontify()
}
})
}
~~~
## 5 总结
>[info] 数据绑定实现了对数据层set与get的劫持与刷新操作关联
>[info]Observer实现对数据属性的set/get的劫持
>[info]Dep实现对set操作的消息广播数组的管理
>[info]Watcher对应特定消息的订阅者,可以实现为数据层刷新或者UI层刷新
## 6 参考
[vue的数据绑定实现](https://segmentfault.com/a/1190000004384515)
- 概述
- 框架结构
- 编译入口(\entries)
- web-compiler.js(web编译)
- web-runtime.js(web运行时)
- web-runtime-wih-compiler.js(web编译运行)
- web-server-renderer.js(web服务器渲染)
- 核心实现 (\core)
- index.js(核心入口)
- config.js(核心配置)
- core\util(核心工具)
- core\observer(双向绑定)
- core\vdom(虚拟DOM)
- core\global-api(核心api)
- core\instance(核心实例)
- 模板编译(\compiler)
- compiler\parser(模板解析)
- events.js(事件解析)
- helper.js(解析助手)
- directives\ref.js(ref指令)
- optimizer.js(解析优化)
- codegen.js(渲染生成)
- index.js(模板编译入口)
- web渲染(\platforms\web)
- compiler(web编译目录)
- runtime(web运行时目录)
- server(web服务器目录)
- util(web工具目录)
- 服务器渲染(\server)
- render-stream.js(流式渲染)
- render.js(服务器渲染函数)
- create-renderer.js(创建渲染接口)
- 框架流程
- Vue初始化
- Vue视图数据绑定
- Vue数据变化刷新
- Vue视图操作刷新
- 框架工具
- 基础工具(\shared)
- 模板编译助手
- 核心实例工具
- Web渲染工具
- 基础原理
- dom
- string
- array
- function
- object
- es6
- 模块(Module)
- 类(Class)
- 函数(箭头)
- 字符串(扩展)
- 代理接口(Proxy)
- 数据绑定基础
- 数据绑定实现
- mvvm简单实现
- mvvm简单使用
- vdom算法
- vdom实现
- vue源码分析资料