好家伙,了解一下Vue如何实现数据劫持
首先,我得搞清楚这玩意的概念,我们先从vue的使用开始吧
想想看,我们平时是如何使用vue的data部分的?
无非是这两种情况
(你可千万不要带着惊讶的表情说"啊!原来有两种写法的吗")
//函数写法
data() {
return {
msg: "I like beef"
}
}
//对象写法
data:{
return {
msg: "I like beef"
}
}
像这样:
对属性的读取和修改拦截
简单来说就是数据的任何变化都要能监测到,这样才能根据数据变化做对应操作
就像"劫持"这个词的意思"抢过里来,盯着"
Vue2最好用的部分----响应式数据,数据一经更改,页面上的数据就会进行局部更新
如果不进行数据劫持,不知道数据状态就无法更新数据
然后我们开始思考,数据劫持是从什么时候开始的?
在 Vue 中,数据劫持是在创建 Vue 实例时完成的。
具体来说,当你实例化一个 Vue 对象时,Vue 会通过使用 Object.defineProperty() 方法来劫持(或称为监听)对象的属性,以便在属性被访问或修改时能够执行相应的操作。
Vue 的数据劫持是通过将数据对象传递给一个称为“响应式系统”的函数来实现的。
这个函数会遍历数据对象的所有属性,并为每个属性设置 getter 和 setter。
当我们获取或修改这些属性时,getter 和 setter 会触发对应的操作,以实现数据的响应式更新。
(并非源码,这是一个例子)
//对对象中的属性进行劫持
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 } }) }
深度代理明天更...