reactive创建的响应式对象解构后为什么会失去响应式
自从专注于React之后,已经有段时间没有用过Vue了,因此最近在学习Vue3.0,Vue的更新机制与React的更新机制是不同的,React的更新机制说的简单点就是根据场景调用不同方法触发状态更新,从而再次进行渲染,而对于Vue的话,我认为是在发生的数据更新时,根据情况进行渲染的。说的专业点就是Vue拥有一个响应式系统,可以让它在数据更新的时候自动进行视图的更新。在Vue3.0中,可以使用reactive声明响应式状态 ,官方例子:
import { reactive } from 'vue'// 响应式状态
const state = reactive({count: 0
})
也可以创建独立的响应式值:
import { reactive } from 'vue'// 响应式状态
import { ref } from 'vue'const count = ref(0)
那么本文重点来了,在学习到reactive方法的时候,看到文档说不要解构reactive创建的响应式对象,为什么?,因为会失去响应式的功能,那为什么会失去,因为…(并没有解释),而且在观看一个尤大讲解Vue3的视频中,尤大也说了不要解构reactive创建的响应式对象,为什么?,因为会失去响应式的功能,那为什么会失去,因为…(并没有解释)。这个问题隔了几天直到我调试Vue3.0的reactivity之后,我才有了一丝想法,可以简单的看看在调用reactivity方法之后发生了什么:
①先有个例子:
<div id="app"><p @click="change">{{refCount}}{{count}}</p></div>
//js代码const { reactive, toRefs } = Vue;const vm = Vue.createApp({setup(props) {//创建响应式对象const rObj = reactive({count: 0});//创建点击事件const change = () => {console.log(rObj.count)rObj.count++;}//利用ref保留与源对象的响应式关联const { count:refCount } = toRefs(rObj);const { count } = rObj;return {//具有响应式refCount,//响应式丢失count,change}}}).mount('#app');
可以看出当点击元素的时候,refCount是随着进行变化的,而count是解构出来的,而它并没有随着变化的。那么调试进入reactive方法:
可以看到它在内部调用了createReactiveObject方法,这名字很好理解就是创建响应式对象,调试进去:
它在这里做了一些处理,细节暂时不探究,重点在这:
创建了一个代理对象将其保存在内部并返回,学习Vue3或多或少都听过Vue3如何进行数据视图更新的,Proxy对数据进行了拦截,当数据发生变化,通知Vue进行视图变化,在new Proxy的第二个参数,它通常使用的baseHanderls:
const baseHandlers = {get(target, key, receiver) {},set(target, key, value, receiver) {},deleteProxy: (target, key) {},has: (target, key) {},ownKey: (target) {}};
绕了这么久可以看出reactive方法其实就是创建了一个Proxy对象,以及进行了一系列处理,其中并没有找到它可能会失去响应式的情况,也就是说它失去响应式不在于Vue而是在于Proxy对象本身,那么可以简化一下:
const obj = {count: 1};const proxy = new Proxy(obj, {get(target, key, receiver) {console.log("这里是get");return Reflect.get(target, key, receiver);},set(target, key, value, receiver) {console.log("这里是set");return Reflect.set(target, key, value, receiver);}});
打印出来的效果:
这时想一下如何会因为解构而失去响应式(在这里就当作是打印文字),先试试直接赋值会打印啥:
proxy.count = 2;
是因为解构相当于重新赋值给另一个变量的原因吗,也就是说它变成了一个新值:
let {count} = proxy;count = 2;
这里会打印什么,因为失去响应,所以它只打印出来:
好像是这样的感觉,那试试对象:
const obj = {a: {count: 1}};function reactive(obj) {return new Proxy(obj, {get(target, key, receiver) {console.log("这里是get");if (typeof target[key] === "object") {return reactive(target[key]);};return Reflect.get(target, key, receiver);},set(target, key, value, receiver) {console.log("这里是set");return Reflect.set(target, key, value, receiver);}});};const proxy = reactive(obj);
直接赋值:
proxy.a.count = 2;console.log(proxy);
先只解构一次看看
let { a } = proxy;a.count = 3;console.log(proxy);
解构到底
let { a } = proxy;let { count } = a;count = 3;console.log(proxy);
为什么会不同,其实很好理解,只解构一次,其实新的对象的count仍然是被代理的,
而解构两次,直接获取了count,相当于绕过了代理a。
那么就很好理解了,解构为什么会失去响应,用这个图就可以解释:
因为解构赋值相当于直接跳过了代理那一层,在下面直接获取值,所以get和set无法被调用。
reactive创建的响应式对象解构后为什么会失去响应式相关推荐
- js 对象解构_JS对象:解构
js 对象解构 JS对象:TL; DR (JS Objects: TL;DR) JavaScript has been plagued since the beginning with misunde ...
- ES6-4/5 解构赋值、函数默认值、数组解构、对象解构
ES-4 解构赋值.函数默认值.数组解构.对象解构 ES-5 隐式转换.函数参数解构.解构本质.()用法 一 解构赋值 1 虚值 含义:在Boolean转换结果为假的值falsy 2 函数默认值 ES ...
- TypeScript基础-数组结构和对象解构
解构数组 Typescript 数组解构和JavaScript类似 let input = [1, 2]; let [first, second, three] = input; console.lo ...
- ES6基础2(块级作用域、数组对象解构)-学习笔记
文章目录 ES6基础2(块级作用域.数组对象解构)-学习笔记 块级作用域 数组解构 对象解构 字符串解构 函数的参数解构 ES6基础2(块级作用域.数组对象解构)-学习笔记 块级作用域 //let c ...
- ES6/06/ES6简介,ES6新增语法,let声明变量,const声明常量,var,let和const总结,数组解构,对象解构,箭头函数,剩余参数
ES6简介 ES全称:ECMAScript ; 由ECMA国际化组织制定的标准脚本语言的标准化规范: 为什么使用ES6? 每一次标准的诞生都意味着语言的完善,功能的加强,JavaScript语言本身也 ...
- JS解构赋值:数组解构和对象解构
一种为变量赋值的新语法,一次可以为多个变量赋值. 分成两种情况: 数组解构 let [变量的集合] = [正常的数组] 举例说明: let [x, y, z] = [10, 16, 21]; 上述代码 ...
- ES6中的对象解构赋值
解构赋值: 解构赋值语法是一个Javascript表达式,这使得可以将数据从数组或对象提取到不同的变量中(这段话是mdn中关于解构赋值的定义,注意这里的定义,可以看出解构主要用在数组和对象上). 说白 ...
- JavaScript对象解构
JS对象解构 1. 什么是对象解构 ? 2. 基础使用 2.1) 变量在解构表达式中声明 变量直接使用属性的名称 变量使用自定义名称 2.2) 变量在解构表达式前声明 3. 嵌套解构 4. 函数参数列 ...
- 解构里面再次解构_解构后的咖啡:焙炒,研磨和分层,以获得更浓的意式浓缩咖啡
解构里面再次解构 Over a year ago, I developed a technique called staccato espresso where I used a sifter to ...
最新文章
- ui设计怎样做出有效果的视觉层级?
- HTML5 Dashboard – 那些让你激动的 Web 技术
- nagios插件之登陆防火墙实现session监控
- 树莓派wifi环境下初始化及环境配置
- pat德才论(java)
- iOS之深入解析Block的底层原理
- 前端学习(1355)模板语法循环
- SharePoint要在master page中动态显示List数据的几种方式
- ajax delete 传递参数,springMVC使用PUT、DELETE方法传递参数解决方案
- 【BZOJ1188】分裂游戏,博弈
- python路径设置方法,R不转义,以及r转义出错SyntaxError
- 东北大学材料成型机械设备课后作业答案汇总
- PC电脑控制手机iphone(iOS 11、iOS 12、iOS 13),需越狱
- arcgis符号库匹配不对的原因_ArcGIS符号库自动匹配方法
- 三国志·魏书·田豫传
- Android UpdateApk 增量更新
- 好消息!想入深户的伙伴们赶紧看过来!
- html实现凹陷效果,css3怎么实现字体凹陷凸出效果?(附代码)
- 【购房必备知识】成都公积金贷款/商业贷款的一些知识记录
- 【Python 教程】11_基础数据类型