一,概述
响应式,个人理解就是数据a变更,会自动更新所有用到a的地方。即它变更后会自动更新所有依赖于它的地方。
具体在vue的代码中有这么几个地方。
1,html中渲染展示绑定的数据
2,watch和conputed中的依赖项
那如何实现自动更新?
首先需要能捕获它的变更,这样才可以在它变更的时候,去更新和它相关的地方。
现有的捕获数据变更的方式有以下三种:
1,利用Object.definePropery数据劫持。 2,利用Proxy数据代理。 3,利用对象的 get 和 set 函数
二,非响应式数据
最开始的时候,我们的代码时按照顺序执行的。
let single = 1; let double = single * 2; console.log(double); single = 2; console.log(double);//这时候double还是2
可以看到,代码按照顺序执行,single发生变化后,并不会更新依赖于它的double,所以这个single就不是一个响应式的数据。
三,基于Object.defineProperty实现
vue2的数据响应就是利用它实现的。
const handleClick = function () {
obj.single++; console.log(obj.single, double); }; const handleDouble = val => val * 2; let obj = {
}; let single = 2; let double = handleDouble(single); Object.defineProperty(obj, 'single', {
get() {
return single; }, set(val) {
single = val; docble = handleDouble(val); //依赖于它的值需要更新一次 } });
这里用obj这个对象,使用Object.defineProperty拦截了对其属性single的访问和修改,而修改时,我们就能在set函数中捕获对它的修改,从而去执行跟新相关数据的方法。(这里只有double依赖于它变化,所以执行更新double的方法。)
使用这个方法有一些缺点:
1,只有监听的属性才能被劫持。在vue2中体现出来就是一开始数据就要写在data中,要监听新增的属性需要用额外的api:this.$set。 2,删除属性时,不会被监听到。比如删除 obj.single 属性,set 函数就不会执行,double 还是之前的数值。体现在Vue 2 中,我们需要 $delete 一个专门的函数去删除数据。
四,基于Proxy实现
Proxy 是针对对象来监听,而不是针对某个具体属性,所以不仅可以代理那些定义时不存在的属性,还可以代理更丰富的数据结构,比如 Map、Set 等,并且我们也能通过 deleteProperty 实现对删除操作的代理。
vue3中的reactive就是采用的这种方式。
let handleDouble = n => n * 2; let obj = {
single: 1 }; let double = handleDouble(obj.single); let proxy = new Proxy(obj, {
get: function (target, prop) {
return target[prop]; }, set: function (target, prop, value) {
target[prop] = value; if (prop === 'single') {
double = handleDouble(value); } return true; } }); const handleClick = function () {
proxy.single++; console.log(proxy.single, double); };
这里使用proxy来代理obj这个对象,当我们修改proxy.single的时候,会被set函数捕获,从而修改obj.single的值。
值得注意的是,peoxy捕获的是该对象内 所有的变更。所以需要根据prop来判断变更的是哪个属性,然后针对这个属性完成它相关项的更新(handleDouble(value))。
五,基于对象的 get 和 set 函数
这种响应式的实现方式,只能拦截某一个属性的修改。vue3中的ref就是采用的这种方式。
let handleDouble = n => n * 2; let ref = function (val) {
let single = val; return {
get value() {
return single; }, set value(val) {
single = val; double = handleDouble(val); } }; }; let singleTest = ref(1); let double = handleDouble(singleTest.value); const handleClick = function () {
singleTest.value++; console.log(singleTest.value, double); };
当修改singleTest的值的时候,set函数会捕获这种改变,从而更新double的值。
这就是在vue3中为啥访问ref声明的参数时,需要加.value的原因。
六,总结
实际上,所谓的响应式数据,就是做到了以下两个事情。
1,能够捕获该数据的变更。 2,该数据变更后能自动调用更新依赖于它的相关页面/数据
到此这篇响应式数据的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/sjkxydsj/10971.html