Vue源码学习(一):数据劫持(对象类型)
阅读原文时间:2023年09月01日阅读:3

好家伙,了解一下Vue如何实现数据劫持

1.Vue中data的使用

首先,我得搞清楚这玩意的概念,我们先从vue的使用开始吧

想想看,我们平时是如何使用vue的data部分的?

无非是这两种情况

(你可千万不要带着惊讶的表情说"啊!原来有两种写法的吗")

**//函数写法
data() {
return {
msg: "I like beef"
}
}

//对象写法
data:{
return {
msg: "I like beef"
}
}**

像这样:

2.那么什么是数据劫持?

对属性的读取和修改拦截

简单来说就是数据的任何变化都要能监测到,这样才能根据数据变化做对应操作

就像"劫持"这个词的意思"抢过里来,盯着"

3.为什么要用数据劫持?

Vue2最好用的部分----响应式数据,数据一经更改,页面上的数据就会进行局部更新

如果不进行数据劫持,不知道数据状态就无法更新数据

4.如何实现数据劫持

然后我们开始思考,数据劫持是从什么时候开始的?

在 Vue 中,数据劫持是在创建 Vue 实例时完成的

具体来说,当你实例化一个 Vue 对象时,Vue 会通过使用 Object.defineProperty() 方法来劫持(或称为监听)对象的属性,以便在属性被访问或修改时能够执行相应的操作。

Vue 的数据劫持是通过将数据对象传递给一个称为“响应式系统”的函数来实现的。

这个函数会遍历数据对象的所有属性,并为每个属性设置 getter 和 setter。

当我们获取或修改这些属性时,getter 和 setter 会触发对应的操作,以实现数据的响应式更新。

5.代码部分:

(并非源码,这是一个例子)

**//对对象中的属性进行劫持
function defineReactive(data, key, value) {
Object.defineProperty(data, key, {
get() {
// console.log('获取')
return value
},
set(newValue) {
// console.log('设置')
if (newValue == value) {
return;
}
value = newValue
}
})

}**

关于defineProperty()方法:Object.defineProperty() - JavaScript | MDN (mozilla.org)

这是一个简化版的数据劫持示例。

这个 defineReactive() 函数接受一个数据对象 `data`、一个属性名 `key` 和初始值 `value`,并使用 Object.defineProperty() 方法定义了一个 getter 和一个 setter。

在 getter 中,当获取属性值时,会返回存储在 `value` 变量中的当前值。

在 setter 中,当尝试设置属性值时,会将新值存储在 `value` 变量中,

这个 defineReactive() 函数可以用于对对象中的某个属性进行劫持,使得在对该属性进行访问或修改时能够触发相应的操作。

完整的例子:

**export function observer(data) {
// console.log(data)

//判断数据  
if (typeof data != 'object' || data == null) {  
    return data  
}  
//对象通过一个类  
return new Observer(data)  

}

class Observer {
constructor(value) {
Object.defineProperty(value, "__ob__", {
enumerable: false,
value: this
})
//判断数据
// console.log(value)
if (Array.isArray(value)) {
//value.__proto__ = ArrayMethods
// console.log("shuzhu")
//如果你是数组对象
//this.observeArray(value)
} else {
this.walk(value)
}
}
walk(data) {
let keys = Object.keys(data)
for (let i = 0; i < keys.length; i++) {

        //对象我们的每个属性进行劫持  
        let key = keys\[i\]  
        let value = data\[key\]  
        defineReactive(data, key, value)  
    }

}  
observeArray(value) { //\[{a:1}\]  
    for (let i = 0; i < value.length; i++) {  
        observer(value\[i\])  
    }  
}  

}
//对对象中的属性进行劫持
function defineReactive(data, key, value) {
observer(value) //深度代理
Object.defineProperty(data, key, {
get() {
// console.log('获取')
return value
},
set(newValue) {
// console.log('设置')
if (newValue == value) {
return;
}
observer(newValue)
value = newValue
}
})

}**

深度代理明天更…