Post

Modern Vue Props Syntax

An overview of the updated props declaration syntax in Vue3, including the more flexible withDefaults and defineProps patterns.

Modern Vue Props Syntax

新项目,写组件传值,没太关注 Vue 版本更新,照着以前的习惯来:

1
2
3
4
5
6
7
8
<script setup lang="ts">
const props = defineProps({
  title: {
    type: String,
    default: "",
  },
});
</script>

不显式 assign props 也可以,但后面要用到值,还是写出来方便。用的时候 props.title 直接拿。

写着写着,想着既然是对象,直接解构不是更简洁:

1
2
3
4
5
6
<script setup lang="ts">
const { title } = props;
const handleClick = () => {
  console.log(title);
};
</script>

然后发现不对劲——template 里用 title,父组件改了值,页面没反应。脑子转了一圈才反应过来:props 解构之后响应式丢了,title 只是解构那一刻的快照,之后父组件怎么改都跟它没关系了。

要用解构,得配 toRefs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script setup lang="ts">
import { toRefs } from "vue";
const props = defineProps({
  title: {
    type: String,
    default: "",
  },
});
const { title } = toRefs(props);

const handleClick = () => {
  console.log(title.value); // 还得加 .value
};
</script>

每次解构都要 import toRefs,用的时候还要 .value。习惯了倒也还好,但总感觉在多走一步,有点 annoying。

Vue 3.5:直接解构,响应式不丢

Vue 3.5 把这个问题从根上解决了——defineProps 的返回值现在可以直接解构,响应式自动保留:

1
2
3
4
5
6
7
8
9
10
11
<script setup lang="ts">
const { title } = defineProps({
  title: {
    type: String,
  },
});

const handleClick = () => {
  console.log(title); // 不需要 .value
};
</script>

爱上了。

默认值也不用在 defineProps 里写 default 了,解构时直接赋:

1
2
3
4
5
6
7
<script setup lang="ts" name="my-card">
const { title = "你好" } = defineProps({
  title: {
    type: String,
  },
});
</script>

如果是 TypeScript,还有更简洁的泛型写法,选项对象整个省掉:

1
2
3
<script setup lang="ts" name="my-card">
const { title = "你好" } = defineProps<{ title?: string }>();
</script>

title?? 表示 optional,默认值就在解构里给。类型和默认值一行搞定,很 TS。

纯 JS 项目没有泛型语法,还是要用对象形式,不过写法上影响不大:

1
2
3
4
5
<script setup lang="js" name="my-card">
const { title = "你好" } = defineProps({
  title: String,
});
</script>
This post is licensed under CC BY 4.0 by the author.