美文网首页Vue
一、为什么Vue实例化后,通过this.能获取到data内的数据

一、为什么Vue实例化后,通过this.能获取到data内的数据

作者: zackxizi | 来源:发表于2018-08-14 17:12 被阅读0次

    一. 从github获取vue开发版本的源码

    git clone https://github.com/vuejs/vue.git
    

    二. 从实例化vue (new vue)开始讲解

    想了解“为什么Vue实例化后,通过this.能获取到data内的数据”必须对call函数内置方法有所了解,如有认识模糊的话可以参考JS的call方法的作用解释,简单易懂

    1. new 实例化Vue首先进入的src/core/instance/index.js

    // vue其实就是 function 实现的 class
    function Vue (options) {
      if (process.env.NODE_ENV !== 'production' &&
        !(this instanceof Vue)
      ) {
        warn('Vue is a constructor and should be called with the `new` keyword')
      }
      // new Vue进行初始化 Vue 并将options 参数传入_init 内 ,this._init 是原型中的方法 ,这个init方法来自于 ‘./init’ 中
      this._init(options)
    }
    

    在实例化时,执行this._init(options),这个_init内置方法是下面initMixin(Vue)增加的

    2. 进入src/core/instance/init.js 查看initMixin方法

    initState(vm) // 初始化状态(这个状态包含data props methods), 这个初始化解决了实例化是通过 this 获取 data 
    

    3. 进入src/core/instance/state.js查看initState方法

    initData(vm)就是Vue实例化后,初始化data 通过this.能获取到data内的数据

    // 初始化状态(这个状态包含data props methods), 这个初始化解决了实例化是通过 this 获取 data props methods 内数据
    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) {
        // 初始化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)
      }
    }
    

    initMixin内执行了initState,初始化data数据

    function initData (vm: Component) {
      let data = vm.$options.data
      data = vm._data = typeof data === 'function'
        ? getData(data, vm)
        : data || {}
      if (!isPlainObject(data)) {
        data = {}
        process.env.NODE_ENV !== 'production' && warn(
          'data functions should return an object:\n' +
          'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
          vm
        )
      }
      // 对比props methods data中的 key 是否相同 如果相同报出警告  禁止相同
      // proxy data on instance
      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 (process.env.NODE_ENV !== 'production') {
          if (methods && hasOwn(methods, key)) {
            warn(
              `Method "${key}" has already been defined as a data property.`,
              vm
            )
          }
        }
        if (props && hasOwn(props, key)) {
          process.env.NODE_ENV !== 'production' && warn(
            `The data property "${key}" is already declared as a prop. ` +
            `Use prop default value instead.`,
            vm
          )
        } else if (!isReserved(key)) {
          proxy(vm, `_data`, key)
        }
      }
      // observe data
      observe(data, true /* asRootData */)
    }
    

    initData 方法中getData将就是实现Vue实例化后,通过this.能获取到data内的数据

    data = vm._data = typeof data === 'function'
        ? getData(data, vm)
        : data || {}
    

    我们再看看 getData方法是怎样实现Vue实例化后,通过this.能获取到data内的数据

    export function getData (data: Function, vm: Component): any {
      // #7573 disable dep collection when invoking data getters
      pushTarget()
      try {
        // data 函数执行的时候将 return 内的数据 返回出来 vm函数可以通过 this. 获取到data 内的数据 ,也就是我们在实例的时候将 this. 能获取到data 内数据原因
        return data.call(vm, vm)
      } catch (e) {
        handleError(e, vm, `data()`)
        return {}
      } finally {
        popTarget()
      }
    }
    

    三、总结

    不卖关子啦!其实Vue实例化的时候,通过getData方法中call修改this指针来实现Vue实例后能获取到data体内的数据,小伙伴可能感觉认为我将vue初始化部分流程拉出来是的你越来越糊涂,但是如果我不讲上面的代码拉出来,我直接来这句总结,你会更加懵的🙂🙂🙂

    相关文章

      网友评论

        本文标题:一、为什么Vue实例化后,通过this.能获取到data内的数据

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