Vue

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

2018-08-14  本文已影响0人  zackxizi

一. 从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初始化部分流程拉出来是的你越来越糊涂,但是如果我不讲上面的代码拉出来,我直接来这句总结,你会更加懵的🙂🙂🙂

上一篇 下一篇

猜你喜欢

热点阅读