Vue响应式原理
vue实现响应式原理的核心是Object.defineProperty
。因为Object.defineProperty
是 ES5 中一个无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器。
当我们将一个普通的Javascript对象传给实例的data选项,Vue会遍历此对象的所有属性,并且使用Object.defineProperty
把这些属性全部都转换为getter/setter
可能听了上面一段话还没太懂,慢慢来,也可以看看官方文档Vue深入响应式原理官方文档
IMG–Vue
Object.defineProperty
首先来看看什么是Object.defineProperty
?
我们可以先去看看MDN Object.defineProperty语法
在这里我们可以这样理解Object.defineProperty
定义的是属性的属性
。对!没错属性也是有属性的。
一般属性的属性有
- [[configurable]] 属性是否可删除(默认true 可删除)
- [[enumerable]] 属性是否可枚举(默认true 可枚举,能通过for循环遍历)
- [[value]] 属性的值 (默认undefined)
- [[writable]] 属性是否可赋值运算(默认true 可运算)
- [[get]] 提供 getter 的方法,当 访问 该属性时,该方法会被执行
- [[set]] 提供 setter 的方法,当 修改 该属性时,该方法会被执行,该方法将接受唯一参数,即该属性新的参数值。
定义静态属性
在我们平时来定义一个对象的属性其实是静态属性,当我们在控制台打印的时候vm.name
只会返回zhangsan
var vm ={
name: 'zhangsan',
age: 11
}
定义响应属性
我们定义整个属性可以说是 动态属性,
var vm = {}
var data = {
name: 'zhangsan',
age: 16
}
var key
for (key in data){
(function(key){
// 定义属性的属性
Object.defineProperty(vm,key,{
get: function (){
console.log('get')
return data[key]
},
set: function (newVal){
console.log('set')
data[key] = newVal
}
})
})(key)
}
打开控制台输入vm,对比两次vm打印出来的内容明显是不一样的。
当我们访问属性的时候会触发get函数,修改属性的时候会触发set函数
vm:{}
age: (...)
name: (...)
get age: ƒ ()
set age: ƒ (newVal)
get name: ƒ ()
set name: ƒ (newVal)
__proto__: Object
vm:
{name: "zhangsan", age: 11}
age: 11
name: "zhangsan"
__proto__: Object
结语:
-
通过Object.defineProperty监听数据的get,set来做一些我们想去做的事情(像是vue vdom数据更新的updateComponent)
-
将data属性代理到了vm上