Vue3.5中解构props,让父子组件通信更加丝滑

前言

在Vue3.5版本中响应式 Props 解构终于正式转正了,这个功能之前一直是试验性的。这篇文章来带你搞清楚,一个String类型的props经过解构后明明应该是一个常量了,为什么还没丢失响应式呢?本文中使用的Vue版本为欧阳写文章时的最新版Vue3.5.5

关注公众号:【前端欧阳】,给自己一个进阶vue的机会

看个demo

我们先来看个解构props的例子。

父组件代码如下:




父组件代码很简单,给子组件传了一个名为name的prop,name的值为字符串“ouyang”。

子组件的代码如下:




在子组件中我们将name给解构出来了并且赋值给了localName,讲道理解构出来的localName应该是个常量会丢失响应式的,其实不会丢失。

我们在浏览器中来看一下编译后的子组件代码,很简单,直接在network中过滤子组件的名称即可,如下图:
network

从上面可以看到原本的console.log(localName)经过编译后就变成了console.log(__props.name),这样当然就不会丢失响应式了。

我们再来看一个另外一种方式解构的例子,这种例子解构后就会丢失响应式,子组件代码如下:




在上面的例子中我们不是直接解构defineProps的返回值,而是将返回值赋值给props对象,然后再去解构props对象拿到localName
network2

从上图中可以看到这种写法使用解构的localName时,就不会在编译阶段将其替换为__props.name,这样的话localName就确实是一个普通的常量了,当然会丢失响应式。

这是为什么呢?为什么这种解构写法就会丢失响应式呢?别着急,我接下来的文章会讲。

从哪里开下手?

既然这个是在编译时将localName处理成__props.name,那我们当然是在编译时debug了。

还是一样的套路,我们在vscode中启动一个debug终端。
debug-terminal

在之前的 通过debug搞清楚.vue文件怎么变成.js文件文章中我们已经知道了vue文件中的

在处理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。

千百度
© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容