SOURCE

console 命令行工具 X clear

                    
>
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] //触发get
    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>