Vue源码研究01-数据响应式原理-让数据变成可观察的
响应式系统:vue中定义在data中的数据,发生变化,会影响对应的视图,Vue是基于Object.defineProperty实现的。
认识Object.defineProperty(obj, prop, descriptor)
函数的说明
直接在一个对象上定义一个新属性或者修改一个对象的现有属性,并返回该对象。
obj: 要定义属性的对象
prop: 要定义或修改属性的名称
descriptor : 要定义或修改的属性描述符
有哪些属性描述符?
- enumrable: 属性是否可枚举,默认false。
- configurable:属性是否可以被修改或者删除,默认false。
- get:获取属性的方法。当访问属性时,会调用此函数。
- set: 设置属性的方法。当属性被修改时,会调用此函数。
get和set是响应式系统实现的核心,vue可以在get方法中得知是否访问了属性,在set方法中得知属性是否被修改。可以这样理解,当将数据绑定到对应的视图上时,实际上是进行了数据的读操作,会触发get方法,此时我们记录触发get方法的位置,这样我们就可以知道哪些地方使用了这个属性。当修改数据时,实际上是进行了数据的写操作,会触发set方法,此时我们更新刚刚记录触发get方法位置的DOM,就会将数据再次渲染到页面上。
图解如下:

代码演示:
function observe (value, cb) {
// 遍历所有属性 将属性响应式化 这里为了便于理解 去掉了递归的过程
Object.keys(value).forEach(key => defineReactive(value, key, value[key], cb))
}
function defineReactive (obj, key, val, cb) {
Object.defineProperty(obj, key, {
enumerable: true, // 属性可以枚举
configurable: true, // 属性可以被修改或删除
get: () => {
// 在这里会进行依赖收集
console.log('触发get方法')
return val
},
set: newVal => {
val = newVal;
cb(); // 这里我们触发渲染
}
})
}
class Vue {
constructor (options) { // Vue的构造函数
this._data = options.data; // 这里的data可以看做是Vue项目组件中的data
observe(this._data, options.render) // 将data中的数据响应化,即变成可观察的,属性的读和写,都会被Vue知道
}
}
let app = new Vue({
el: '#app',
data: {
text: 'text',
text2: 'text2'
},
render () {
console.log('render')
}
})
app._data.text // 调用get方法
app._data.text = '测试' // 属性值被修改,set方法会被调用
知己知彼,百战不殆!