细说为什么vue2里面data可以直接通过this访问

106 阅读1分钟

今天在学习vue2 源码中思考了一个问题 为什么vue2里面data可以直接通过this访问

然后在百度上一顿搜、 感觉都没有说的那么细致,所以来记录一下

首先我们不看源码 直接来做一个小实验

    //创建两个测试对象
    let testA = {
        a: "22222"
    }

    let testB = {
        b: "11111"
    }
    

这个时候我想直接通过testB.a 访问到testA.a的数据

因为testB 不存在 a 所以我们需要去做一个反向代理


Object.defineProperty(testB, 'a', {
        enumerable: true,
        configurable: true,
        get() {
            return testA.a
        }
 })
 console.log(testB.a)

image.png !咦 虽然testB上面没有a 但是我们通过反向代理也成功的取到testA里面a的值 让我们再打印testB看一下

console.log(testB.a)

image.png

!咦testB上有一个a的引用 测试反向代理完成然后让我们再看看源码

源码部分

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')
  }
  this._init(options)
}
// 初始化所有的业务
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)

这里我们进入initMixin(Vue)

// 初始化状态
 initState(vm)

进入 initState(vm)

export function initState(vm: Component) {
  vm._watchers = []
  const opts = vm.$options
  // 初始化props
  if (opts.props) initProps(vm, opts.props)
  // 初始化methods
  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) {
    // 初始化watch
    initWatch(vm, opts.watch)
  }
}

进入初始化initData(vm)找到

proxy(vm, `_props`, key)

proxy具体代码

const sharedPropertyDefinition = {
  enumerable: true,
  configurable: true,
  get: noop,
  set: noop
}
// 数据代理 把this._data[key] 代理到this[key]上
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)
}

这里对比上面的的测试例子应该就可以一目了然的知道为什么为什么vue2里面data可以直接通过this访问了