美文网首页
Vue源码解析(三)之 data

Vue源码解析(三)之 data

作者: Love小六六 | 来源:发表于2019-08-21 01:07 被阅读0次

    为什么可以直接使用 data

    • 基于上一篇的 demo ,我们可以在 mounted 生命周期里获取 message
    import Vue from 'vue'
    new Vue({
      el: '#app',
      mounted() {
        console.log(this.message)
      },
      data() {
        return {
          message: 'Hello'
        }
      }
    })
    
    • message 是定义在 data 里的, 为什么通过 this.message 可以直接获取呢?

    core/instance/init.js中,执行了一系列 mixin, 其中 initState 函数做了一些特殊处理

    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)
      // 当vm.$options.data存在时执行initData
      if (opts.data) {
        initData(vm)
      } else {
        observe(vm._data = {}, true)
      }
      if (opts.computed) initComputed(vm, opts.computed)
      if (opts.watch && opts.watch !== nativeWatch) {
        initWatch(vm, opts.watch)
      }
    }
    

    initData

    function initData (vm: Component) {
      let data = vm.$options.data
      data = vm._data = typeof data === 'function'
        ? getData(data, vm)
        : data || {}
      if (!isPlainObject(data)) {
        data = {}
      }
      const keys = Object.keys(data)
      const props = vm.$options.props
      const methods = vm.$options.methods
      let i = keys.length
      while (i--) {
        const key = keys[i]
        if (props && hasOwn(props, key)) {
        } else if (!isReserved(key)) {
          proxy(vm, `_data`, key)
        }
      }
      observe(data, true)
    }
    
    • 分析 initData 函数,const keys = Object.keys(data)获取到 data 里的值,然后执行proxy(vm, `_data`, key)

    • proxy 函数

    export function proxy (target: Object, sourceKey: string, key: string) {
      sharedPropertyDefinition.get = function proxyGetter () {
        return this[sourceKey][key]
      }
      sharedPropertyDefinition.set = function proxySetter (val) {
        this[sourceKey][key] = val
      }
      Object.defineProperty(target, key, sharedPropertyDefinition)
    }
    
    • 通过 Object.defineProperty,vm.message 实际上就是 vm._data.message

    demo 调试

    • 在 initData 里 将 vm._data 赋值为 getData(data, vm), 即 {message: "Hello"}, key 为 message
    • 因此经过 proxy 可得 vm.message = vm._data.message

    相关文章

      网友评论

          本文标题:Vue源码解析(三)之 data

          本文链接:https://www.haomeiwen.com/subject/cglvsctx.html