数据代理、数据劫持概念
数据劫持
data中数据通过各种逻辑和封装变成_data
,从而去监测data数据的变化,一旦发现data中数据变化了,_data
就去修改页面,这个过程通过Object.defineProperty实现,叫数据劫持
数据代理
_data
中数据拿出放在vm
身上,就可以直接通过vm.name
,不需要vm._data.name
通过Object.defineProperty()
实现,这个过程叫数据代理
Object.defineProperty()
方法
- es5新增的一个方法
- 作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性
语法:
js
Object.defineProperty(obj,prop,desc)
// obj:在哪个对象身上添加或者修改属性
// prop:添加或修改的属性名
// desc:配置项,一般是一个对象
/*
desc 配置项还有6个配置属性
value: "jack", 给属性添加指定属性值
writable: true, 默认false不可以修改,true属性可以被修改
enumerable: true, 默认false不可以遍历,true可以被遍历
configurable: true, 默认false不能删除,true可以被删除
get(){}, 当读取属性值的时候,getter就会被调用,函数的返回值会作为该属性的值
set(){}, 当修改属性值的时候,getter就会被调用,该方法将接受唯一参数,即该属性新的参数值
*/
注意:
- 当使用了 getter 或 setter 方法,不允许使用 writable 和 value这两个属性
- 不要在 gette r中再次获取该属性值,也不要在 setter 中再次设置该属性,否则会栈溢出
示例:
js
let person = {
name:"码农",
age: 18
}
Object.defineProperty(person,'sex',{
value:"男", //设置属性值
enumerable:true, //控制属性是否可以枚举,默认值是false
writable:true, //控制属性是否可以被修改,默认值是false
configurable:true //控制属性是否可以被删除,默认值是false
})
console.log(person)
数据代理
数据代理的概念
数据代理(Data Proxy):
- 通过访问代理对象的属性,来间接访问目标对象的属性
- 在 Vue 中,将
data
对象中的属性代理到 Vue 的实例上 - 这样一来,我们可以通过直接访问 Vue 实例来访问和修改其
data
对象的属性(这就是为什么直接Vue的实例 . 就可以访问到属性以及方法的底层原理) - 更加方便的操作data中的数据
Vue数据代理对属性名的要求
- data对象的属性名不可以以 " _ "或 " $ " 开头,
- 因为Vue的实例上的属性名以 " _ " 或 " $ " 开头,会产生冲突
数据劫持
数据劫持(Data Interception):
- 数据劫持是指在访问或修改对象的属性时,对这些操作进行拦截和监视,以便在属性发生变化时能够触发相关的操作。
- 在 Vue 中,数据劫持用于监听数据的变化,以实现双向绑定和响应式更新
- Vue 通过在数据对象的属性上使用
Object.defineProperty
来实现数据劫持 - 每当访问属性或修改属性时,Vue 会触发相应的
get
和set
拦截器,从而实现对数据变化的监听 - 通过数据劫持,Vue 能够在属性发生变化时自动触发视图的更新,从而实现了响应式的特性
Vue数据代理、数据劫持底层实现
html 代码部分
html
<script src='./myVue.js'></script>
<div id ="root"></div>
<script>
let vm = new MyVue({
el: '#root',
data(){
return{
name: '张三',
age:18
}
},
methods: {
fn(){
console.log('我是方法');
}
}
});
</script>
js 代码部分
js
class MyVue {
//简单实现数据代理
constructor(options) {
Object.keys(options.data()).forEach((item, index) => {
Object.defineProperty(this, item, {
get() {
console.log('读取了数据',item);
return options.data()[item]
},
set(value) {
console.log('修改了数据',item,value);
options.data()[item] = value
}
})
})
// 简单实现methods
Object.keys(options.methods).forEach(item =>{
this[item] = options.methods[item]
})
}
}