1. // initData
    2. const data = { msg: 'msg' }
    3. observe(data)
    1. // observe
    2. function observe(data) {
    3. if (!isObject(value)) return;
    4. return new Observer(data)
    5. }
    1. // Class Observe
    2. class Observe {
    3. value: any;
    4. dep: Dep;
    5. vmCount: number;
    6. constructor (data) {
    7. this.value = data
    8. this.dep = new Dep()
    9. this.vmCount = 0
    10. data._ob_ = this
    11. this.walk(data)
    12. }
    13. walk(obj) {
    14. const keys = Object.keys(obj)
    15. for (let i = 0; i < keys.length; i++) {
    16. defineReactive(obj, keys[i])
    17. }
    18. }
    19. }
    20. // 这一步完成之后会将我们data定义一个_ob_属性 说明以及做过响应式处理
    1. class Dep {
    2. static target: ?Watcher;
    3. id: number;
    4. subs: Array<Watcher>;
    5. constructor () {
    6. this.id = uid++
    7. this.subs = []
    8. }
    9. addSub (sub: Watcher) {
    10. this.subs.push(sub)
    11. }
    12. removeSub (sub: Watcher) {
    13. remove(this.subs, sub)
    14. }
    15. depend () {
    16. if (Dep.target) {
    17. Dep.target.addDep(this) // watcher 添加对应的dep
    18. }
    19. }
    20. notify () {
    21. const subs = this.subs.slice()
    22. for (let i = 0, l = subs.length; i < l; i++) {
    23. subs[i].update() // 调用对应的watcher更新
    24. }
    25. }
    26. }
    1. function defineReactive(obj, key) {
    2. const dep = new Dep()
    3. let childOb = observe(val) // 子对象 { msgData: {msg: ''} } => observe({ msg: ''})
    4. Object.defineProperty(obj, key,{
    5. get() {
    6. if (Dep.target) {
    7. dep.depend() // watcher实例 添加对应的dep
    8. }
    9. if (childOb) {
    10. childOb.dep.depend()
    11. }
    12. retun obj[key]
    13. },
    14. set(newVal) {
    15. val = newVal
    16. childOb = observe(newVal)
    17. dep.notify()
    18. }
    19. })
    20. }
    1. // 假设一个data为以下数据
    2. const data = {
    3. msg: 'msg',
    4. formData: {
    5. name: 'zyh'
    6. }
    7. };
    8. // 进行过响应式过后为:
    9. const data = {
    10. msg: 'msg',
    11. formData: {
    12. name: 'zyh',
    13. _ob_: Observe{ value: formData, dep: Dep }
    14. },
    15. _ob_: Observe{ value: data, dep: Dep }
    16. };

    何时触发get呢?
    接着手动调用$mount(‘#app’)

    1. Vue.prototype.$mount = function(el) {
    2. const options = this.$options
    3. const { render, staticRenderFns } = compileToFunctions(template) // 生成render函数
    4. return mount.call(this, el, hydrating)
    5. }
    1. Vue.prototype.$mount = function(el) {
    2. return mountComponent(this, el)
    3. }
    1. function mountComponent(vm, el) {
    2. vm.$el = el
    3. if (!vm.$options.render) vm.$options.render = createEmptyVNode // 生成一个空节点
    4. let updateComponent = () => {
    5. vm._update(vm._render(), hydrating)
    6. }
    7. new Watcher(vm, updateComponent, ()=>{}, {}, true /* isRenderWatcher */)
    8. }
    1. class Watcher {
    2. constructor(
    3. vm: Component,
    4. expOrFn: string | Function,
    5. cb: Function,
    6. options?: ?Object,
    7. isRenderWatcher?: boolean
    8. ) {
    9. this.vm = vm
    10. if (isRenderWatcher) {
    11. vm._watcher = this
    12. }
    13. vm._watchers.push(this)
    14. this.getter = expOrFn // updateComponent
    15. this.value = this.get()
    16. }
    17. get() {
    18. const vm = this.vm
    19. value = this.getter.call(vm, vm) // 开始执行 vm._update(vm._render(), hydrating)
    20. }
    21. }

    vm._update 在哪定义呢 lifecycleMixin

    1. Vue.prototype._update

    梳理下流程:

    1. 定义响应式数据
    2. 执行挂载
    3. 生成render函数
    4. 执行mountComponent函数
    5. new Wather
    6. wather 内部调用get Dep.target = this(watcher)
    7. wather 内部调用vm._update(vm._render(), hydrating)
    8. 调用render函数生成vnode,这一步触发 getter 依赖收集Dep.targe(wather)
    9. set触发dep.notify ```typescript const data = { obj: { foo: { bar: ‘bar’ } }, name: ‘kobe’ }

    // 1. this.data.obj = this.obj this.data.name = this.name // 2. this.obj getter 触发getter 的 依赖收集 // 3. this.obj.foo // // 4. 赋值触发setter

    1. ```typescript
    2. dep.depend Dep.target:watcher
    3. // class Dep
    4. // 目的还是添加watcher
    5. depend () {
    6. if (Dep.target) {
    7. Dep.target.addDep(this)
    8. }
    9. }
    10. addSub (watcher) {
    11. this.subs.push(sub)
    12. }
    13. // class Watcher
    14. addDep (dep: Dep) {
    15. const id = dep.id
    16. if (!this.newDepIds.has(id)) {
    17. this.newDepIds.add(id)
    18. this.newDeps.push(dep)
    19. if (!this.depIds.has(id)) {
    20. dep.addSub(this)
    21. }
    22. }
    23. }
    1. // 对数组的原型方法进行拦截扩展
    2. protoAugment(value, arrayMethods) // value: []
    3. const arrayMethods = Object.create(Array.prototype)
    4. function protoAugment (target, src: Object) {
    5. /* eslint-disable no-proto */
    6. target.__proto__ = src
    7. /* eslint-enable no-proto */
    8. }
    9. const methodsToPatch = [
    10. 'push',
    11. 'pop',
    12. 'shift',
    13. 'unshift',
    14. 'splice',
    15. 'sort',
    16. 'reverse'
    17. ]
    18. /**
    19. * Intercept mutating methods and emit events
    20. */
    21. methodsToPatch.forEach(function (method) {
    22. // cache original method
    23. const original = arrayProto[method]
    24. def(arrayMethods, method, function mutator (...args) {
    25. const result = original.apply(this, args)
    26. const ob = this.__ob__
    27. let inserted
    28. switch (method) {
    29. case 'push':
    30. case 'unshift':
    31. inserted = args
    32. break
    33. case 'splice':
    34. inserted = args.slice(2)
    35. break
    36. }
    37. if (inserted) ob.observeArray(inserted)
    38. // notify change
    39. ob.dep.notify()
    40. return result
    41. })
    42. })