console
function defineReactive(data, key, value) {
observer(value)
var dep = new Dep()
Object.defineProperty(data, key, {
configurable: true,
enumerable: true,
set: function(newVal) {
value = newVal;
dep.notify()
console.log(`属性${key}被监听`)
},
get: function() {
if(Dep.target) {
dep.addSub(Dep.target)
}
return value
}
})
}
function observer(data) {
console.log(data)
if(!data || typeof data !== "object") return false;
console.log(111)
Object.keys(data).forEach(key => {
defineReactive(data, key, data[key])
})
}
function Dep() {
this.subs = []
}
Dep.prototype.addSub = function(watcher) {
this.subs.push(watcher)
}
Dep.prototype.notify = function() {
this.subs.forEach(function(sub) {
sub.update()
})
}
function Watcher(vm, exp, cb) {
this.vm = vm;
this.exp = exp;
this.cb = cb;
this.value = this.get()
}
Watcher.prototype.get = function() {
Dep.target = this
var value = this.vm.data[this.exp]
Dep.target = null;
return value
}
Watcher.prototype.update = function() {
this.run()
}
Watcher.prototype.run = function() {
var value = this.vm.data[this.exp]
var oldValue = this.value;
if(oldValue != value) {
this.cb.call(this.vm, value, oldValue)
}
}
function SelfVue(data, el, exp) {
this.data = data;
Object.keys(this.data).forEach(key => {
this.proxyKeys(key)
})
observer(data);
el.innerHTML = this.data[exp]
new Watcher(this, exp, function(val) {
el.innerHTML = val
})
}
SelfVue.prototype.proxyKeys = function(key) {
var self = this;
Object.defineProperty(this, key, {
configurable: false,
enumerable: false,
set: function proxySetter(val) {
self.data[key] = val
},
get: function proxyGetter() {
return self.data[key]
}
})
}
var data = {
name: 'xyz',
age: 10
}
var selfVue = new SelfVue(data, document.getElementById('aa'), 'name')
setTimeout(function() {
selfVue.name = 'zzz'
}, 2000)
<div id="aa">{{name}}}</div>