参考: vue2.0源码分析之理解响应式架构
](https://segmentfault.com/a/1190000007334535)
// 参考:https://segmentfault.com/a/1190000007334535
function VNode(tag, data, children, text) {
return {
tag: tag,
data: data,
children: children,
text: text
}
}
class Vue {
constructor(options) {
this.$options = options
this._data = options.data
Object.keys(options.data).forEach(key => this._proxy(key))
observer(options.data)
// 调用watch方法时会执行render方法,该方法中会触发date[key]的get方法
const vdom = watch(this, this._render.bind(this), this._update.bind(this))
}
_proxy(key) {
const self = this
Object.defineProperty(self, key, {
configurable: true,
enumerable: true,
get: function proxyGetter () {
return self._data[key]
},
set: function proxySetter (val) {
_data[key] = val
}
})
}
_update() {
console.log("我需要更新");
const vdom = this._render.call(this)
}
_render() {
return this.$options.render.call(this)
}
__h__(tag, attr, children) {
return VNode(tag, attr, children.map((child)=>{
if(typeof child === 'string'){
return VNode(undefined, undefined, undefined, child)
}else{
return child
}
}))
}
__toString__(val) {
return val == null ? '' : typeof val === 'object' ? JSON.stringify(val, null, 2) : String(val);
}
}
function observer(value, cb){
Object.keys(value).forEach((key) => defineReactive(value, key, value[key] , cb))
}
function defineReactive(obj, key, val, cb) {
const dep = new Dep()
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: ()=>{
if(Dep.target){
console.log('现在的值:', val)
dep.add(Dep.target)
}
return val
},
set: newVal => {
if(newVal === val)
return
val = newVal
dep.notify()
}
})
}
function watch(vm, exp, cb){
Dep.target = cb // Dep相当于是一个全局变量
let vdom = exp()
Dep.target = null //清空Dep,区别是普通的 get还是查找依赖时的 get
return vdom
}
class Dep {
constructor() {
this.subs = []
}
add(cb) {
this.subs.push(cb)
}
notify() {
this.subs.forEach((cb) => cb())
}
}
Dep.target = null
// --------------------
var demo = new Vue({
el: '#demo',
data: {
text: "before",
},
render(){
return this.__h__('div', {}, [
this.__h__('span', {}, [this.__toString__(this.text)])
])
}
})
setTimeout(function(){
demo.text = "after"
}, 3000)
console.log('Dep.target', Dep.target)
console.log('demo.text', demo.text)
网友评论