class Observe {
constructor (data) {
if (!data || typeof data !== 'object') return
this.data = data
this.walk()
}
walk () {
Object.keys(this.data).forEach(function(val, key){
this.propretyRactive(this.data,val,this.data[val])
}, this)
}
propretyRactive(data, key, val){
//为了保证每层的值都能添加getter,setter方法进行回调
new Observe(val)
var dep = new Dep()
Object.defineProperty(data, key, {
get (){
if (Dep.target){
dep.addSub(Dep.target)
}
return val
},
set (newVal) {
if (newVal !== val) {
val = newVal
// 为新值添加getter,setter方法
new Observe(val)
dep.notify()
}
}
})
}
}
//发布者类
class Dep {
constructor () {
this.subs = []
}
addSub (sub) {
if (!this.subs.includes(sub)){
this.subs.push(sub)
}
}
notify () {
this.subs.forEach(function(val){
val.update()
})
}
}
Dep.target = null
//订阅者类
class Watcher {
constructor (vm, keys, updateCb) {
this.vm = vm
this.keys = keys
this.updateCb = updateCb
this.value = this.get()
}
get () {
Dep.target = this
var value = this.vm.data
let key = this.keys.split('.')
//隐式调用getter方法。从而将订阅者添加到发布者的通知列表
key.forEach(_key=>{
value = value[_key]
})
Dep.target = null
return value
}
update () {
let newVal = this.get()
if (newVal !== this.value){
this.value = newVal
this.updateCb.call(this.vm)
}
}
}
var data = {
test: 1,
testObj: {
tb1: 1
}
}
var vm = new Observe(data)
new Watcher(vm, 'test', function(){
console.dir('test已更新')
})
new Watcher(vm, 'testObj.tb1', function(){
console.dir('testObj.tb1已更新')
})
data.testObj.tb1 = 2
Vue 响应式布局原理解析
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 上一篇:全面深入理解响应式原理(上)-对象基础篇 我们首先来看下改变数组的两种方式: 对于这两种改变数据的方式,v...
- 上一篇:Vue原理解析(五):彻底搞懂虚拟Dom到真实Dom的生成过程 vue之所以能数据驱动视图发生变更的关键,...
- 二、ES中的mappingES的mapping如何用?什么时候需要手动,什么时候需要自动?Mapping,就是对索...