Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue官网中的约束源码解释 -- 数据与方法 #11

Open
muwoo opened this issue Apr 26, 2018 · 0 comments
Open

Vue官网中的约束源码解释 -- 数据与方法 #11

muwoo opened this issue Apr 26, 2018 · 0 comments

Comments

@muwoo
Copy link
Owner

muwoo commented Apr 26, 2018

当一个 Vue 实例被创建时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的所有的属性。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。

// 我们的数据对象
var data = { a: 1 }

// 该对象被加入到一个 Vue 实例中
var vm = new Vue({
  data: data
})

// 获得这个实例上的属性
// 返回源数据中对应的字段
vm.a == data.a // => true

// 设置属性也会影响到原始数据
vm.a = 2
data.a // => 2

// ……反之亦然
data.a = 3
vm.a // => 3

为什么不是访问vm.$options.data.a而是 vm.a

其实我们知道,为new Vue({data: ...})的时候,会进行mergeOptions,也就是吧所有的参数挂载到vm.$options中,我们定义的data也是会被挂载进去,那么,为什么我们可以通过vm.a来取到我们想要的值呢?我们来看一下源码的实现:

// core/instance/state.js
function initData (vm: Component) {
  let data = vm.$options.data
  data = vm._data = typeof data === 'function'
    ? getData(data, vm)
    : data || {}
   ...
}

Vue通过initData函数,为实例vm定义了一个_data属性,他的值等于我们的vm.$options.data。并做了函数处理,因为有可能我们是通过一个functionreturn一个data。那到这一步,我们顶多可以通过this._data.xx来访问属性,那如何实现this.xx来访问呢?我们接着来看:

...
const keys = Object.keys(data)
let i = keys.length
while (i--) {
  ...
   proxy(vm, `_data`, key)
}
...

我们省略了一些代码,主要来看核心的实现。首先我们会遍历data中定义的属性,然后有一个proxy这样的东西

const sharedPropertyDefinition = {
  enumerable: true,
  configurable: true,
  get: noop,
  set: noop
}
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函数来定义了target = vmsourceKey = _datakey = xx。并改写了target.keygetset方法。
到这里我们就明白了,当我们访问this.xx的时候,其实是被Object.defineProperty拦截了,代理到this._data.xx上面。

@muwoo muwoo changed the title Vue官网中的阅读源码解释(一) -- 数据与方法 Vue官网中的阅读源码解释 -- 数据与方法 Apr 26, 2018
@muwoo muwoo changed the title Vue官网中的阅读源码解释 -- 数据与方法 Vue官网中的约束源码解释 -- 数据与方法 Apr 27, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant