Vue3 Props 属性

一、Props 是什么?

想象一下,你正在组装一个乐高机器人。机器人的头部、手臂、腿部都是独立的组件。为了让手臂知道它应该连接在身体的哪个位置,你需要给它一个"连接点"的指令。在 Vue3 中,Props 就是这个"指令",它是父组件向子组件传递数据的一种方式

简单来说:Props 是组件的自定义属性,父组件通过它来给子组件"喂"数据。

二、Props 的核心作用

Props 主要解决组件间的通信问题,具体作用如下:

  • 数据传递:父组件可以把数据(字符串、数字、数组、对象等)传递给子组件。
  • 配置组件:通过传递不同的 Props 值,可以让同一个子组件呈现不同的状态或行为,实现复用。
  • 单向数据流:数据只能从父组件流向子组件,这保证了数据变化的可预测性,便于调试。
  • 类型检查 :Vue3 的 Composition API 和 `<script setup>` 语法支持对 Props 进行类型定义,提升代码健壮性。

三、Props 的属性(Props 选项)

在 Vue3 中,定义 Props 时可以配置多种属性来约束和描述数据。以下是常用的 Props 属性:

  • type :指定 Prop 的数据类型,如 StringNumberBooleanArrayObjectDateFunctionSymbol,或自定义构造函数。
  • required:布尔值,表示该 Prop 是否为必传项。
  • default:指定 Prop 的默认值。可以是固定值,也可以是一个返回默认值的函数。
  • validator:自定义验证函数,用于校验传入的 Prop 值是否有效。

四、如何接受和使用 Props(代码案例)

1. 使用 `<script setup>` 语法(推荐)

这是 Vue3 组合式 API 中最简洁的写法。

提示:带有define开头的都是宏声明属性,不需要引入

html 复制代码
<!-- 子组件 ChildComponent.vue -->
<template>
  <div>
    <h3>子组件</h3>
    <p>接收到的标题:{{ title }}</p>
    <p>接收到的数量:{{ count }}</p>
    <p>用户信息:{{ user.name }} ({{ user.age }}岁)</p>
    <ul>
      <li v-for="item in items" :key="item">{{ item }}</li>
    </ul>
  </div>
</template>

<script setup>
// 使用 defineProps 宏来声明 Props
const props = defineProps({
  // 类型 + 必填
  title: {
    type: String,
    required: true
  },
  // 类型 + 默认值
  count: {
    type: Number,
    default: 0
  },
  // 对象类型 + 默认值函数
  user: {
    type: Object,
    default: () => ({ name: '匿名', age: 18 })
  },
  // 数组类型
  items: {
    type: Array,
    default: () => []
  },
  // 自定义验证器
  score: {
    type: Number,
    validator: (value) => {
      return value >= 0 && value <= 100;
    }
  }
});

// 在模板或逻辑中直接使用 props.title, props.count 等
console.log(props.title);
</script>
html 复制代码
<!-- 父组件 ParentComponent.vue -->
<template>
  <div>
    <h2>父组件</h2>
    <ChildComponent
      title="用户列表"
      :count="userCount"
      :user="currentUser"
      :items="todoList"
      :score="85"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const userCount = ref(5);
const currentUser = ref({ name: '张三', age: 25 });
const todoList = ref(['学习 Vue', '写代码', '阅读文档']);
</script>

补充:数组形式的 defineProps

除了使用对象形式 定义 Props 外,defineProps 也支持简单的数组形式。

defineProps 是有返回值的

javascript 复制代码
<script setup>
// 数组形式:仅声明属性名,所有属性类型默认为任意类型
const props = defineProps(['title', 'count', 'user']);

// 在模板中可以直接使用
console.log(props.title); // 来自父组件传递的值
console.log(props.count);
</script>
  • 推荐做法: 在正式项目中,为了更好的代码健壮性和开发体验,建议使用对象形式(如上方示例)或 TypeScript 泛型形式来定义 Props,以便获得完整的类型检查和 IDE 提示。

2. 使用 TypeScript 与类型标注

结合 TypeScript 可以获得更完善的类型提示和检查。

typescript 复制代码
<!-- 子组件 ChildComponent.vue -->
<template>
  <!-- 同上 -->
</template>

<script setup lang="ts">
interface User {
  name: string;
  age: number;
}

// 使用接口定义 Props 类型
interface Props {
  title: string;
  count?: number; // 可选
  user: User;
  items: string[];
  score?: number;
}

// 使用泛型 defineProps
const props = defineProps<Props>();

// 或者提供默认值(需要 withDefaults 辅助函数)
const propsWithDefaults = withDefaults(defineProps<Props>(), {
  count: 0,
  user: () => ({ name: '匿名', age: 18 }),
  items: () => [],
});
</script>

3. 使用选项式 API

这是 Vue2 风格的写法,在 Vue3 中仍然兼容。

javascript 复制代码
<!-- 子组件 ChildComponent.vue -->
<template>
  <!-- 同上 -->
</template>

<script>
export default {
  name: 'ChildComponent',
  // 在 props 选项中声明
  props: {
    title: {
      type: String,
      required: true
    },
    count: {
      type: Number,
      default: 0
    },
    user: {
      type: Object,
      default: () => ({ name: '匿名', age: 18 })
    },
    items: {
      type: Array,
      default: () => []
    },
    score: {
      type: Number,
      validator: function(value) {
        return value >= 0 && value <= 100;
      }
    }
  },
  setup(props) {
    // 在 setup 函数中访问 props
    console.log(props.title);
    return {};
  }
}
</script>

五、使用 Props 的注意事项

  • 单向数据流 :不要在子组件内部直接修改 Props(Vue 会警告)。如果需要修改,应该在子组件内定义一个新的响应式数据(如使用 refcomputed)来接收 Prop 的初始值。
  • Prop 命名 :在 JavaScript 中使用 camelCase(如 userName),在模板中建议使用 kebab-case(如 user-name)。
  • 动态与静态传递 :使用 : 绑定是动态传递(响应式),不使用 : 是静态字符串传递。
  • 复杂对象默认值 :对象或数组的 default 必须是一个工厂函数返回新对象,避免多个组件实例共享同一引用。
相关推荐
zh_xuan37 分钟前
个人主页左侧菜单支持分组,以及菜单显示和隐藏
前端·javascript·css
Ming_studying1 小时前
HTML + CSS + JavaScript实现可视化JSON工具:格式化、折叠、搜索与错误定位
javascript·css·html·json·数据可视化·web工具
Emily156853598704 小时前
Emerson 1C31129G03 Analog Input Module
java·开发语言·前端·plc·emerson·1c31129g03·input module
To_OC9 小时前
面试被问了三回三栏布局,这次我终于把 BFC 那层窗户纸捅破了
前端·css·面试
To_OC9 小时前
啃完 TS 工具类型我发现:Pick 和 Omit 原来就是一层窗户纸
前端·面试·typescript
风月说与山鬼11 小时前
三、大括号语法
前端·react.js
kyriewen11 小时前
我把最常踩的8个CORS跨域报错整理了一遍——第8个去年还不存在
前端·javascript
Csvn11 小时前
🕰️ 闭包 + setTimeout 的 5 个经典陷阱:为什么定时器看到的永远不是最新的值?
前端
lilian23312 小时前
Harmony os 技术实战|拼豆制图27:用单字符编码承载 50 张 70×70 图纸
前端·数据库·华为·harmonyos