网站建设须知,四川大学网站seo诊断报告,网站打开速度很慢,ui动效网站数据响应式是什么#xff1f;
所谓 数据响应式 就是建立 响应式数据 与 依赖#xff08;调用了响应式数据的操作#xff09;之间的关系#xff0c;当响应式数据发生变化时#xff0c;可以通知那些使用了这些响应式数据的依赖操作进行相关更新操作#xff0c;可以是DOM…数据响应式是什么
所谓 数据响应式 就是建立 响应式数据 与 依赖调用了响应式数据的操作之间的关系当响应式数据发生变化时可以通知那些使用了这些响应式数据的依赖操作进行相关更新操作可以是DOM更新也可以是执行一些回调函数。
Vue2 和 Vue3 响应式的区别
从Vue2 到 Vue3 都使用了响应式那么它们之间有什么区别
Vue2响应式基于Object.defineProperty()实现的。Vue3响应式基于Proxy()实现的。
为什么Vue3会选择Proxy()替代defineProperty()看下面两个例子
Vue2响应式
// Vue2响应式声明
defineReactive(data,key,val){Object.defineProperty(data,key,{enumerable:true,configurable:true,get:function(){console.log(对象属性:${key}访问defineReactive的get)return val;},set:function(newVal){if(valnewVal){return;}val newVal;console.log(对象属性:${key}访问defineReactive的set)}})
}Vue2定义对象
let obj {};
this.defineReactive(obj,name,sapper);// 修改obj的name属性
obj.name 小明;
console.log(obj,obj.name);// 为obj添加age属性
obj.age 18;
console.log(obj,obj);
console.log(obj.age,obj.age);// 为obj添加数组属性
obj.hobby [游戏, 原神];
obj.hobby[0] 王者;
console.log(obj.hobby,obj.hobby);// 为obj添加对象属性
obj.student {school:大学};
obj.student.school 学院;
console.log(obj.student.school,obj.student.school); 从上图可以看出使用defineProperty()定义了包含name属性的对象obj然后添加age属性、添加hobby属性数组、添加student属性对象并分别访问都没有触发obj对象中的get、set方法。也就是说defineProperty()定义对象不能监听添加额外属性或修改额外添加的属性的变化再看这样一个例子
let obj {};
// 初始化就添加hobby
this.defineReactive(obj,hobby,[游戏, 原神]);
// 改变数组下标0的值
obj.hobby[0] 王者;
console.log(obj.hobby,obj.hobby); 假设一开始就为obj添加hobby属性发现修改数组下标0的值并没有触发obj里的set方法也就是说defineProperty()定义对象不能监听根据自身数组下标修改数组元素的变化注意如果是直接用defineProperty()定义数组元素是可以监听的但是对于数组比较大的时候就很牺牲性能尤其考虑到性能就没有使用这种方法。
Vue3响应式
看一下Proxy代理的对象例子
// proxy实现
let targetProxy {name:sapper};
let objProxy new Proxy(targetProxy,{get(target,key){console.log(对象属性:${key}访问Proxy的get)return target[key];},set(target,key,newVal){if(target[key]newVal){return;}console.log(对象属性:${key}访问Proxy的set)target[key]newVal;return target[key];}
})
对象应用
// 修改objProxy的name属性
objProxy.name 工兵;
console.log(objProxy.name,objProxy.name);// 为objProxy添加age属性
objProxy.age 12;
console.log(objProxy.age,objProxy.age);// 为objProxy添加hobby属性
objProxy.hobby [游戏, 原神];
objProxy.hobby[0] 王者;
console.log(objProxy.hobby,objProxy.hobby);// 为objProxy添加对象属性
objProxy.student {school:大学};
objProxy.student.school 学院;
console.log(objProxy.student.school,objProxy.student.school); 从上图可以发现Proxy与defineProperty的明显区别之处Proxy能支持对象添加或修改触发get、set方法不管对象内部有什么属性。
defineProperty
Object.defineProperty()
defineProperty() 定义对象不能监听添加额外属性或修改额外添加的属性的变化defineProperty() 定义对象不能监听根据自身数组下标修改数组元素的变化。
Vue里的用法例子 data() {return {name: sapper,student: {name: sapper,hobby: [原神, 天涯明月刀],},};},methods: {deleteName() {delete this.student.name;console.log(删除了name, this.student);},updateArr() {this.student.hobby[0] 王者;console.log(更新了this.student的hobby, this.student);},addItem() {this.student.age 21;console.log(添加了this.student的属性, this.student);}
}上图中确实可以修改data里的属性但是页面不能及时渲染所以Vue2提供了两个属性方法解决了这个问题Vue.$set和Vue.$delete。 注意不能直接this._ data.age这样去添加age属性也是不支持的。 this.$delete(this.student, name); // 删除student对象属性name
this.$set(this.student.hobby, 0, 王者); // 更新student对象属性hobby数组
this.$set(this.student, age, 21); // 添加student对象属性age上图中可以修改data里的属性并且页面能够及时渲染。
proxy
Proxy解决了上面两个弊端proxy可以实现
可以直接监听对象而非对象属性可以监听对象添加额外属性的变化;
const user {name:张三}
const obj new Proxy(user,{get:function (target,key){console.log(get run);return target[key];},set:function (target,key,val){console.log(set run);target[key]val;return true;}
})
obj.age 22;
console.log(obj); // 监听对象添加额外属性打印 set run! 可以直接监听数组的变化。
const obj new Proxy([2,1],{get:function (target,key){console.log(get run);return target[key];},set:function (target,key,val){console.log(set run);target[key]val;return true;}
})
obj[0] 3;
console.log(obj); // 监听到了数组元素的变化打印 set run! Proxy 返回的是一个新对象而 Object.defineProperty() 只能遍历对象属性直接修改。 支持多达13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是Object.defineProperty() 不具备的。
总的来说Vue3响应式使用Proxy解决了Vue2的响应式的诟病从原理上说它们所做的事情都是一样的依赖收集和依赖更新。