什么是响应式
- 当我们对data属性进行修改后,vue立刻监听到,并对视图进行更新
Object.defineProperty
- 我们通过new操作符或者是对象字面量创建的对象的属性,是数据属性,对数据属性的获取和修改,都是对该属性的value特性的控制。是无法监控的
var obj = {
name: 'zhangsan',
age:20
}
console.log(obj.name) // zhangsan 获取属性的时候,是无法监听的
obj.age = 25 // 赋值属性的时候,是无法监听的
- 如果想要监听属性的变化,我们可以通过
Object.defineProperty来给对象定义访问器属性(属性分为数据属性和访问器属性)
var obj = {}
var _name = 'lisi' // 下划线,是一种常用的记号,表示只能通过对象的方法访问的属性
Object.defineProperty(obj, 'name', {
get: function () {
console.log('get') // 监听
return _name
},
set: function (newValue) {
console.log('set') // 监听
_name = newValue
}
})
console.log(obj.name) // lisi 当我们在这里访问name属性的时候,后台打印了get,说明我们监听到了get函数被调用了,也就是属性的获取被监听到了
obj.name = 'wangwu' // 这一步是给name赋了一个新值,控制台打印了set,说明我们监听到了set函数被调用了,也就是属性的修改被监听到了

image.png
要想实现vue中的响应式,有两个问题我们要弄明白
- vue中如何使用Object.defineProperty对数据进行监听的呢?
- data属性里的数据,是如何代理到vue实例上的呢?(比如:我们可以直接通过vm.name,访问data里的name属性)
// vm是一个vue实例
// var vm = new Vue({
// el:'#app',
// data:{
// name:'lisi',
// age: 20
// }
// })
// 我们可以模拟一下,vue是怎么监听name和age的变化的,以及name和age怎么代理到vm实例上的
var vm = {}
var data = {
name: 'lisi',
age:20
}
var key, value
for (key in data) {
// 此时key会命中一个闭包,我们需要一个立即执行函数把每个循环到的key保留下来
(function (key) {
Object.defineProperty(vm, key, {
get: function () {
console.log('get',data[key]) // 监听
return data[key]
},
set: function (newVal) {
console.log('set',newVal) // 监听
data[key] = newVal
}
})
})(key)
}
- 通过上面模拟我们可以知道,vue正是通过
Object.defineProperty方法把data的数据属性,变为了访问器属性,这个时候这些属性的读和写都是通过get和set函数完成的。任何对这些属性的读和写的操作都会触发这两个函数,所以我们就可以在这两个函数里写我们的监听逻辑了。
- 至于data对象的属性是怎么代理到vm实例的,也是通过
Object.defineProperty方法,就是遍历data对象,然后把它的属性,都设置为vm实例的访问器属性。
总结,关于vue的响应式怎么理解的回答,主要两点
- 关键是理解 Object.defineProperty
- 将data属性代理到vm上
网友评论