前言
在Vue3.5版本中响应式 Props 解构
终于正式转正了,这个功能之前一直是试验性
的。这篇文章来带你搞清楚,一个String类型的props经过解构后明明应该是一个常量了,为什么还没丢失响应式呢?本文中使用的Vue版本为欧阳写文章时的最新版Vue3.5.5
关注公众号:【前端欧阳】,给自己一个进阶vue的机会
看个demo
我们先来看个解构props的例子。
父组件代码如下:
父组件代码很简单,给子组件传了一个名为name
的prop,name
的值为字符串“ouyang”。
子组件的代码如下:
{{ localName }}
在子组件中我们将name
给解构出来了并且赋值给了localName
,讲道理解构出来的localName
应该是个常量会丢失响应式的,其实不会丢失。
我们在浏览器中来看一下编译后的子组件代码,很简单,直接在network中过滤子组件的名称即可,如下图:
从上面可以看到原本的console.log(localName)
经过编译后就变成了console.log(__props.name)
,这样当然就不会丢失响应式了。
我们再来看一个另外一种方式解构的例子,这种例子解构后就会丢失响应式,子组件代码如下:
{{ localName }}
在上面的例子中我们不是直接解构defineProps
的返回值,而是将返回值赋值给props
对象,然后再去解构props
对象拿到localName
。
从上图中可以看到这种写法使用解构的localName
时,就不会在编译阶段将其替换为__props.name
,这样的话localName
就确实是一个普通的常量了,当然会丢失响应式。
这是为什么呢?为什么这种解构写法就会丢失响应式呢?别着急,我接下来的文章会讲。
从哪里开下手?
既然这个是在编译时将localName
处理成__props.name
,那我们当然是在编译时debug了。
还是一样的套路,我们在vscode中启动一个debug
终端。
在之前的 通过debug搞清楚.vue文件怎么变成.js文件文章中我们已经知道了vue
文件中的模块实际是由
vue/compiler-sfc
包的compileScript
函数处理的。
compileScript
函数位置在/node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js
找到compileScript
函数就可以给他打一个断点了。
compileScript函数
在debug
终端上面执行yarn dev
后在浏览器中打开对应的页面,比如: http://localhost:5173/ 。此时断点就会走到compileScript
函数中。
在我们这个场景中简化后的compileScript
函数代码如下:
function compileScript(sfc, options) {
const ctx = new ScriptCompileContext(sfc, options);
const scriptSetupAst = ctx.scriptSetupAst;
// 2.2 process
在处理defineProps
宏函数时,发现是直接解构了返回值才会进行处理。上面这个例子中没有直接进行解构,而是将其赋值给props
,然后再去解构props
。这种情况下ctx.propsDestructuredBindings
对象中什么都没有。
后续在递归遍历script模块中的所有代码,发现ctx.propsDestructuredBindings
对象中什么都没有。自然也不会将localName
替换为__props.name
,这样他当然就会丢失响应式了。
总结
在编译阶段首先会处理宏函数defineProps
,在处理的过程中如果发现解构了defineProps
的返回值,那么就会将解构的name
属性,以及name
解构到本地的localName
变量,都全部一起存到ctx.propsDestructuredBindings
对象中。
接下来就会去递归遍历script模块中的所有代码,如果发现使用的localName
变量能够在ctx.propsDestructuredBindings
对象中找的到。那么就说明这个localName
变量是由props解构得到的,就会将其替换为__props.name
,所以使用解构后的props依然不会丢失响应式。
关注公众号:【前端欧阳】,给自己一个进阶vue的机会
另外欧阳写了一本开源电子书vue3编译原理揭秘,看完这本书可以让你对vue编译的认知有质的提升。这本书初、中级前端能看懂,完全免费,只求一个star。
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容