Vue3.5中解构props,让父子组件通信更加丝滑
前言
在Vue3.5版本中响应式 Props 解构终于正式转正了,这个功能之前一直是试验性的。这篇文章来带你搞清楚,一个String类型的props经过解构后明明应该是一个常量了,为什么还没丢失响应式呢?本文中使用的Vue版本为最新版Vue3.5.5
demo
我们先来看个解构props的例子。
父组件代码如下:
<template>
<ChildDemo name="ouyang" />
</template>
<script setup lang="ts">
import ChildDemo from "./child.vue";
</script>
父组件代码很简单,给子组件传了一个名为name的prop,name的值为字符串“ouyang”。
子组件的代码如下:
<template>
{{ localName }}
</template>
<script setup lang="ts">
const { name: localName } = defineProps(["name"]);
console.log(localName);
</script>
在子组件中我们将name给解构出来了并且赋值给了localName,讲道理解构出来的localName应该是个常量会丢失响应式的,其实不会丢失。
我们再来看一个另外一种方式解构的例子,这种例子解构后就会丢失响应式,子组件代码如下:
<template>
{{ localName }}
</template>
<script setup lang="ts">
const props = defineProps(["name"]);
const { name: localName } = props;
console.log(localName);
</script>
在上面的例子中我们不是直接解构defineProps的返回值,而是将返回值赋值给props对象,然后再去解构props对象拿到localName。
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 <script setup> body
for (const node of scriptSetupAst.body) {
if (node.type === "VariableDeclaration" && !node.declare) {
const total = node.declarations.length;
for (let i = 0; i < total; i++) {
const decl = node.declarations[i];
const init = decl.init;
if (init) {
// defineProps
const isDefineProps = processDefineProps(ctx, init, decl.id);
}
}
}
}
// 3 props destructure transform
if (ctx.propsDestructureDecl) {
transformDestructuredProps(ctx);
}
return {
//....
content: ctx.s.toString(),
};
}
在之前的 为什么defineProps宏函数不需要从vue中import导入?文章中我们已经详细讲解过了compileScript函数中的入参sfc、如何使用ScriptCompileContext类new一个ctx上下文对象。所以这篇文章我们就只简单说一下他们的作用即可。