乐趣区

关于vue.js:Vuejs-源码剖析响应式原理虚拟-DOM模板编译

学习总结:

1、Vue 首次渲染的过程。
2、Vue 响应式原理。

Vue 响应式的重点就是数据劫持 / 公布订阅模式,其余更多介绍查看 Vue 的官网的 深刻响应式原理一节,这里次要总结一下外部代码的实现。

  1. 先找找入口在哪里(src/core/instance/init.js)

    initState(vm) –> initData(vm) –> observe()

    // 初始化 Vue 实例的状态,初始化了_props,methods,_data,computed,watch
    export function initState (vm: Component) {vm._watchers = []
      const opts = vm.$options
      if (opts.props) initProps(vm, opts.props)
      if (opts.methods) initMethods(vm, opts.methods)
      if (opts.data) {initData(vm) // 看这里
      } else {observe(vm._data = {}, true /* asRootData */)
      } 
      if (opts.computed) initComputed(vm, opts.computed)
      if (opts.watch && opts.watch !== nativeWatch) {initWatch(vm, opts.watch)
      }
    }
    // 把 data 属性属性注入到 Vue 实例上
    function initData(vm) {
        let data = vm.$options.data
        // 初始化 _data, 组件中 data 是函数,调用函数返回后果,否则间接返回 data
        data = vm._data = typeof data === 'function'
            ? getData(data, vm)
            : data || {}
            
        //...
          
        // 响应式解决
        observe(data, true /* asRootData */)
    }
  1. 当初终于到正题了 observe(value) 响应式的入口
    export function observe(alue: any, asRootData: ?boolean) {
        // 判断 value 是否是对象
         if (!isObject(value) || value instanceof VNode) {return}

         let ob: Observer | void
         // 如果 value 有 __ob__(observer 对象) 属性 完结(阐明曾经做过响应化解决)if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {ob = value.__ob__} else if (
            shouldObserve &&
            !isServerRendering() &&
            (Array.isArray(value) || isPlainObject(value)) &&
            Object.isExtensible(value) &&
            !value._isVue
         ) {
             // 创立一个 Observer 对象
             ob = new Observer(value)
         }
         if (asRootData && ob) {ob.vmCount++}
         return ob // 返回 observer 对象
    }

3. 观察者

    export class Observer {
        value: any; // 察看对象
        dep: Dep; // 依赖对象
        vmCount: number; // 实例计数器
        
        constructor (value: any) {
            this.value = value
            this.dep = new Dep()
            this.vmCount = 0 // 初始化实例的 vmCount 为 0
            def(value, '__ob__', this) // 将实例挂载到观察者对象的 __ob__ 属性
            // 数组的响应式解决
            if (Array.isArray(value)) {
                ...
                // 为数组中的每一个对象创立一个 observer 实例
                this.observeArray(value) 
            } else {
                // 遍历对象中的每一个属性,转换成 setter/getter
                this.walk(value)
            }
        }
        
        walk (obj: Object) {
            // 获取察看对象的每一属性
            const keys = Object.keys(obj)
            // 遍历每一个属性,设置为响应式数据
            for (let i = 0; i < keys.length; i++) {defineReactive(obj, keys[i])
            }
        }
        
        // Vue 重写了数组 push,popt,splice 等有副作用的办法,当这些办法被调用的时候,会发送告诉;observeArray (items: Array<any>) {for (let i = 0, l = items.length; i < l; i++) {observe(items[i])
            }
        }
    }
3、虚构 DOM 中 Key 的作用和益处。
4、Vue 中模板编译的过程。
退出移动版