Vue3 Props 属性

一、Props 是什么?

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

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

二、Props 的核心作用

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

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

三、Props 的属性(Props 选项)

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

  • type :指定 Prop 的数据类型,如 String、Number、Boolean、Array、Object、Date、Function、Symbol,或自定义构造函数。
  • 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 会警告)。如果需要修改,应该在子组件内定义一个新的响应式数据(如使用 ref 或 computed)来接收 Prop 的初始值。
  • Prop 命名 :在 JavaScript 中使用 camelCase(如 userName),在模板中建议使用 kebab-case(如 user-name)。
  • 动态与静态传递 :使用 : 绑定是动态传递(响应式),不使用 : 是静态字符串传递。
  • 复杂对象默认值 :对象或数组的 default 必须是一个工厂函数返回新对象,避免多个组件实例共享同一引用。
相关推荐
小poop21 小时前
CSS 基础与实战:从入门到精通网页美化
前端
Csvn1 天前
运行时性能
前端
Never_every991 天前
位图转矢量工具哪个好?实测抠抠图AI位图转矢量工具
大数据·前端
paopaokaka_luck1 天前
宠物门店经营管理系统(销售与库存联动、进货自动记账、 退换与退款关联、员工个人业绩、ECharts 经营分析、滞销识别与客户分层、宠物档案年龄计算)
前端·javascript·spring boot·mysql·echarts·mybatis·1024程序员节
空中湖1 天前
用 React 写数据大屏:为什么我不建议用图表库
前端·react.js·前端框架
欣欣之王来了1 天前
原始HTML插值:v-html指令的使用与安全风险
前端·学习·架构·项目·vue3教程
IT_陈寒1 天前
Redis的LRU淘汰策略坑了我一整天
前端·人工智能·后端
计算机魔术师1 天前
砍半价格、参数再涨,国产旗舰追到 Opus 鼻尖了
前端
paopaokaka_luck1 天前
心理咨询管理系统(WebSocket实时沟通、基于用户的协同过滤、 ECharts多维分析、 预约业务流程、预约校验与定时处理)
java·vue.js·spring boot·mysql·spring·echarts·1024程序员节
特立独行的猫A1 天前
10 MB 的桌面 AI 客户端:用仓颉 + 系统 WebView 替代 Electron
前端·harmonyos