vue最大的特点之一就是数据驱动视图。
一个页面的数据是支撑页面变成一个活页面的基础。
页面中数据变化的原因,可能是由于用户操作或者后端数据的变化引起的,数据data的变化,导致页面模板也随之变化。今天来说一下vue是如何知道数据变化了的。
开门见山,vue监听数据变化其实是用了js自带的标准内置对象 Object 中的一个静态方法 defineProperty
Object.defineProperty
依据vue源码路径:项目中uve源码文件node_modules/vue/src/core/observer/index.js
源码太复杂,我附上我理解的简化过的代码:
监听一个属性时:
const data = {}
let housePriceVal = 180
Object.defineProperty(data, 'price', {
enumerable: true,
configurable: true,
get () {
console.log('price属性被读取了')
return housePriceVal
},
set (newVal) {
console.log('price属性被修改了')
housePriceVal = newVal
}
})
setTimeout(() => {
const price = data.price
console.log('price', price)
}, 500)
setTimeout(() => {
data.price = 200
}, 1000)
在node上运行的结果是:
price属性被读取了
price 180
price属性被修改了
模拟vue监听data下的多个属性:
const data = {
price: 180,
age: 70
}
const observer = function () {
for (const key in data) {
// 重新定义各个属性,监听起来
defineReactive(data, key, data[key])
}
}
const defineReactive = (data, key, value) => {
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get () {
console.log(`${key}属性被读取了`)
return value
},
set (newVal) {
console.log(`${key}属性被修改了`)
value = newVal
// 监听到被修改了可以做各种操作
}
})
}
setTimeout(() => {
console.log('price:', data.price)
}, 500)
setTimeout(() => {
data.price = 200
console.log('price:', data.price)
}, 1000)
observer()
setTimeout(() => {
console.log('price:', data.price)
}, 500)
setTimeout(() => {
data.price = 200
console.log('price:', data.price)
}, 1000)
observer()
node 运行的结果:
price属性被读取了
price: 180
price属性被修改了
price属性被读取了
price: 200
- 所以数据就是这样变得可观测的