Vue是非侵入性的响应式系统。
当你修改数据时,视图会进行相应的变化。所以它是如何追踪变化的?
官方:当你把一个普通的JS对象传入Vue实例作为data选项时,Vue将遍历此对象所有的属性,并使用Object.defineProperty把这些属性全部转为getter/setter。正是因为该方法是es6的,所以Vue不支持IE8及以下版本。
然后,每个组件实例(我感觉应该是每个data里的key键)都对应一个watcher实例(构造函数watcher怎么实现),它会在组件渲染的过程中把“接触”过的数据属性记录为依赖(如何收集依赖)。
当你再对该对象下面的属性进行修改时,将会触发setter(我理解是触发defineProperty里的set函数,set函数会通知watcher执行它的函数)通知watcher重新渲染和它关联的组件。
我认为,正是因为使用了object.defineProperty,所以它只能动态渲染绑定且触发了set/get函数的属性。若你在对象上添加或删除属性,它无法触发set/get函数,也就无法进行实时渲染。
这也是Vue不允许动态添加根级响应式属性的一个原因。还有就是提前声明好所有响应式属性有利用阅读和理解。
Object.defineProperty(obj,property,descriptor)
obj:目标对象
**property**:需要定义的属性或方法的名字。
**descriptor**:目标属性所拥有的特性。
descriptor有6个选项,分别为:
**value**:属性的值
**writable**:如果为false,属性的值就不能被重写,只能为只读了
**configurable**:总开关,一旦为false,就不能再设置他的(value,writable,configurable)
**enumerable**:是否能在for...in循环中遍历出来或在Object.keys中列举出来。
**get**:
在 descriptor 中不能 同时设置访问器 (get 和 set) 和 wriable 或 value,否则会错,就是说想用(get 和 set),就不能用(wriable 或 value中的任何一个).
当对property进行取值时,会触发get对应的函数。
**set**:当对property进行赋值时,会触发set对应的函数。
writable,configurable,enumerable,**默认值为false**。