Skip to content

Props 和自定义事件(父子通信)

在 Vue 中,父子组件通信主要通过 Props(父传子)和自定义事件(子传父)实现。

Props(父传子)

作用

  • 父组件通过属性向子组件传递数据。

基本用法

  1. 父组件传递数据
    html
    <ChildComponent :title="parentTitle" :count="parentCount" />
    javascript
    import { ref } from 'vue';
    const parentTitle = ref('我是父组件标题');
    const parentCount = ref(0);
  2. 子组件接收数据
    vue
    <script setup>
    // 组合式 API:defineProps 宏
    const props = defineProps({
    title: String,       // 类型校验
    count: {
        type: Number,
        default: 1,        // 默认值
        required: true     // 必传
    }
    });
    </script>
    
    <template>
    <h2>{{ title }}</h2>
    <p>计数:{{ count }}</p>
    </template>

关键特性

  1. 类型校验
    • 支持 StringNumberBooleanArrayObject 等原生类型,或自定义类。
    javascript
    defineProps({
        user: Object,
        tags: Array,
        callback: Function
    });
  2. 单向数据流
    • Props 是只读的,子组件不能直接修改父组件传递的值。
    • 如需修改,父组件通过事件接收子组件的请求,由父组件更新数据。
  3. 动态 Props
    • 使用 v-bind 动态绑定
    html
    <ChildComponent :config="dynamicConfig" />

自定义事件(子传父)

作用

  • 子组件通过触发事件向父组件传递数据或通知状态变化。

基本用法

  1. 子组件触发事件
    vue
    <script setup>
    // 组合式 API:defineEmits 宏
    const emit = defineEmits(['updateTitle', 'deleteItem']);
    
    const handleClick = () => {
        emit('updateTitle', '新标题'); // 触发事件并传递数据
    };
    </script>
    
    <template>
        <button @click="handleClick">修改标题</button>
    </template>
  2. 父组件监听事件
    html
    <ChildComponent 
        @update-title="handleUpdateTitle" 
        @delete-item="handleDelete"
    />
    javascript
    const handleUpdateTitle = (newTitle) => {
        console.log('收到新标题:', newTitle);
        parentTitle.value = newTitle; // 更新父组件数据
    };

关键特性

  1. 事件命名规范
    • 推荐使用 kebab-case(如 update-title),因为 HTML 属性不区分大小写。
  2. 传递多个参数
    javascript
    emit('event-name', arg1, arg2, ...);
  3. 事件校验
    • 通过对象语法校验事件参数:
    javascript
    const emit = defineEmits({
        'update-title': (newTitle) => {
            return typeof newTitle === 'string'; // 返回布尔值表示校验是否通过
        }
    });

高级技巧

  1. 双向绑定简化(v-model)
    • 副组件通过 v-model 实现双向绑定(语法糖):
    html
    <!-- 父组件 -->
    <ChildComponent v-model="parentData" />
    
    <!-- 等价于 -->
    <ChildComponent 
        :modelValue="parentData" 
        @update:modelValue="parentData = $event" 
    />
    • 子组件需定义 modelValue 和触发 update:modelValue
    javascript
    defineProps(['modelValue']);
    const emit = defineEmits(['update:modelValue']);
  2. 透传 Attributes($attrs
    • 父组件传递未在子组件 props 中声明的属性,会透传到子组件的根元素。
    • 禁用透传:inheritAttrs: false
  3. 依赖注入(provide/inject
    • 跨层级组件通信(避免逐层传递 props):
    javascript
    // 祖先组件
    provide('theme', 'dark');
    
    // 后代组件
    const theme = inject('theme', 'light'); // 默认值 'light'

对比总结

通信方式方向适用场景
Props父 → 子父组件向子组件传递初始数据
自定义事件子 → 父子组件通知父组件状态变化
v-model双向绑定表单控件或自定义组件简化双向绑定
provide/inject跨层级深层嵌套组件共享数据

常见问题

Q1:为什么不能直接修改 Props?

  • 单向数据流原则:保证数据源唯一性,避免父/子组件数据不一致。
  • 正确做法:子组件触发事件,由父组件修改数据。

Q2:如何监听子组件的生命周期?

  • 父组件使用 @hook:@vnode- 事件(Vue 3 已废弃,改用 emits)。

Q3:动态 Props 名如何实现?

  • 使用 v-bind:[propName]
html
<ChildComponent :[dynamicPropName]="value"/>
编程洪同学服务平台是一个广泛收集编程相关内容和资源,旨在满足编程爱好者和专业开发人员的需求的网站。无论您是初学者还是经验丰富的开发者,都可以在这里找到有用的信息和资料,我们将助您提升编程技能和知识。
专业开发
高端定制
售后无忧
站内资源均为本站制作或收集于互联网等平台,如有侵权,请第一时间联系本站,敬请谅解!本站资源仅限于学习与参考,严禁用于各种非法活动,否则后果自行负责,本站概不承担!