SOURCE

// Vue中是通过Object.defineProperty来进行数据劫持的
class Vue {
    constructor(options) {
        this.$el = options.el
        this.$data = options.data

        if (this.$el) {
            new Observer(this.$data) // 让 $data里面的元素具有数据劫持的能力
            new Compiler(this.$el, this)
        }
    }
}

// Observer类给我们$data中的某一些特定的数据添加数据劫持的能力, 也就是我们的getter 和 setter方法
class Observer {
    constructor(data) {
        this.observer(data)
    }
    observer(data) {
        if (typeof data === 'object' && data != null) {
            for (let key in data) {
                this.defineReactive(data, key, data[key])
            }
        }
    }
    defineReactive(obj, key, value) {
        this.observer(value)
        let dep = new Dep() // 给每个数据添加被观察者
        Object.defineProperty(obj, key, {
            get() {
                Dep.target && dep.addSub(Dep.target)
                return value
            },
            set(newVal) {
                if (newVal != value) {
                    this.observer(newVal)
                    value = newVal
                    dep.notify()
                }
            }
        })
    }
}
/** 
// 观察者 - Watcher类
// Watcher类其实很简单,当我们被观察者发生变化的时候,观察者也会做出对应的变化。
// 观察者 数据一变化 调用回调更新视图
// Watcher内部会根据vm 和表达式如man.name等获取到当前表达式对应的$data的值,然后缓存起来,
当调用updata()方法的时候,如果新值和缓存起来的老值相等,则执行对应的回调函数来更新视图
**/
class Watcher {
    constructor(vm, expr, cb) {
        this.vm = vm
        this.expr = expr
        this.cb = cb
        ths.oldVal = this.get() // 存放一个旧值
    }

    get() {
        Dep.target = this // 将当前的watcher缓存在 Dep.target
        let value = CompilerUnit.getVal(this.vm, this.expr)
        Dep.target = null
        return value
    }
    updata() {
        let newVal = CompilerUnit.getVal(this.vm, this.expr)
        if (newVal != this.oldVal) {
            this.cb(newVal)
        }
    }
}

// 被观察者 - Dep类
// 有了观察者我们也需要有触发观察者update方法的被观察者
// 被观察者 自己的数据变化 通知所有观察者
class Dep {
    constructor() {
        this.subs = []
    }
    addSub(watcher) { // 订阅
        this.subs.push(watcher)
    }
    notify() { // 发布
        this.subs.forEach(watcher => watcher.updata())
    }
}










console 命令行工具 X clear

                    
>
console