ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
>[success] # defineProps `defineProps` 作为编译器宏几个用法特点 * 不需要被导入即可使用,它会在编译`<script setup>`语法块时一同编译掉 * 只能在`<script setup>`中使用 * 接收与`props`选项相同的值 * 必须在`<script setup>`的顶层使用,不可以在`<script setup>`的局部变量中引用。 * `defineProps()`宏中的参数不可以访问`<script setup>`中定义的其他变量,因为在编译时整个表达式都会被移到外部的函数中。 1. 不需要被导入即可使用,它会在编译`<script setup>`语法块时一同编译掉 ~~~html <template> {{ props.name }} </template> <!--在页面可以直接使用。但注意仅限页面--> <template> {{ name }} </template> <script setup> // 无需导入直接使用 const props = defineProps({ name: String, }); </script> <style></style> ~~~ 2. 接收与`props`选项相同的值 ~~~ html <template> {{ props.name }} </template> <script setup> import props from '../Props/props'; // const props = defineProps(['name']); /** * 支持配置字段 type 类型,required 是否必填,default默认值,validator 校验 * interface PropOptions<T> { * type?: PropType<T> * required?: boolean * default?: T | ((rawProps: object) => T) * validator?: (value: unknown) => boolean * } * */ // const props = defineProps({ name: String }); // 设置类型 const props = defineProps({ name: { type: String, require: true, default: '1', validator: (value) => { return value.length > 1; }, }, }); </script> <style></style> ~~~ 3. 必须在`<script setup>`的顶层使用,不可以在`<script setup>`的局部变量中引用。 ~~~html <template> {{ a.name }} </template> <script setup> // 报错不能在局部变量中使用:ReferenceError: defineProps is not defined function aFun() { const props = defineProps({ name: { type: String, require: true, default: '1', validator: (value) => { return value.length > 1; }, }, }); return props; } const a = aFun(); </script> <style></style> ~~~ 4. `defineProps()` 宏中的参数不可以访问 `<script setup>` 中定义的其他变量,因为在编译时整个表达式都会被移到外部的函数中。 ~~~html <template> {{ props.name }} </template> <script setup> const len = 1; const props = defineProps({ name: { type: String, require: true, default: '1', validator: (value) => { // 报错 `defineProps` are referencing locally declared variables return value.length > len; }, }, }); </script> <style></style> ~~~ 5. 只能在`<script setup>`中使用 * 在其他文件声明了一个`defineProps` ~~~ import { defineProps } from 'vue'; export default defineProps({ name: { type: String, require: true, default: '1', validator: (value) => { return value.length > 1; }, }, }); ~~~ * 使用报错 ~~~html <template> <div>测试</div> <children :name="1" /> </template> <script setup> // 警告defineProps() is a compiler-hint helper that is only usable inside <script setup> of a single file component. Its arguments should be compiled away and passing it at runtime has no effect. import children from './components/children.vue'; </script> <style></style> ~~~ >[danger] ##### 其他配置项 1. 所有 prop 默认都是可选的,除非声明了`required: true`。 ![](https://img.kancloud.cn/76/da/76dad43be7747699ae95b4d3e362e2d5_546x157.png) 2. 未传递的 prop 会有一个缺省值`undefined` 3. 如果声明了`default`值,那么在 prop 的值被解析为`undefined`时,无论 prop 是未被传递还是显式指明的`undefined`,都会改为`default`值。 4. 声明多类型 ~~~ defineProps({ disabled: [Boolean, Number] }) ~~~ 5. 可以检测的类型,`String` `Number` `Boolean` `Array` `Object` `Date` `Function` `Symbol` `自定义类` * 自定义类举例子 ~~~ class Person { constructor(firstName, lastName) { this.firstName = firstName this.lastName = lastName } } defineProps({ author: Person }) ~~~ >[danger] ##### 使用技巧 1. **prop 被用于传入初始值;而子组件想在之后将其作为一个局部数据属性。** 在这种情况下,最好是新定义一个局部数据属性,从 prop 上获取初始值即可: ~~~ const props = defineProps(['initialCounter']) // 计数器只是将 props.initialCounter 作为初始值 // 像下面这样做就使 prop 和后续更新无关了 const counter = ref(props.initialCounter) ~~~ 2. **prop 以原始的形式传入,但还需作转换。** 在这种情况中,最好是基于该 prop 值定义一个计算属性: ~~~ const props = defineProps(['size']) // 该 prop 变更时计算属性也会自动更新 const normalizedSize = computed(() => props.size.trim().toLowerCase()) ~~~ >[info] ## 官网 [Props](https://cn.vuejs.org/guide/components/props.html)