Skip to content

Vue 组件反向数据传递

Vue 组件反向数据传递

简介

在使用组件过程中,除了从父组件向子组件正向传递数据外,还有从子组件向父组件的反向数据传递的情况。

比如当子组件想操作父组件正向传递过来的数据时,在子组件中是不能直接进行操作的,需要子组件通知父组件代为操作。

此时,就需要事件监听实现反向数据传递。

Vue 中使用监听自定义事件的方式,实现父子事件中的反向数据传递。

反向传递数据过程

  1. 在父组件中绑定一个自定义事件,并定义该事件的响应方法。
  2. 在子组件中触发自定义事件。
  3. 父组件监听到子组件触发的自定义事件后,执行事件对应的响应方法。

$emit() 方法

$emit() 方法是 Vue 中的内置方法,用于触发事件并向父组件传递数据。

父组件

<script setup>
    import RSC from './RSC.vue';

    function recvMsg(msg){
        alert(msg)
    }
</script>

<template>
    <RSC @msg="recvMsg"  />
</template>

子组件

<template>
    <button @click="$emit('msg', 'Hello Vue')">点击触发msg事件</button>
</template>

注意:

  • $emit() 方法只能在内联事件处理器中使用,不能在自定义的方法中使用。
  • $emit() 方法触发的事件在同一个组件内,是无法直接监听的,如果要监听,需要使用 $on 绑定事件来监听。

defineEmits() 函数 与 emit() 函数

很多情况下,子组件触发事件时并不是在标签的内联事件处理器,而是在一些算定义方法中,此时就需要使用 defineEmits() 函数实现。

  1. defineEmits() 函数(实际是一个宏定义)用来声明注册需要抛出的事件

  2. defineProps() 类似,defineEmits() 仅可用于 <script setup> 之中,并且不需要导入。

  3. defineEmits() 返回一个等同于 $emit 方法的 emit 函数。

  4. 返回的 emit 函数可以被用于在组件的 <script setup> 中抛出事件,因为此处无法直接访问 $emit:

格式

<script setup>
    const emit = defineEmits(['eventNameXxx', ....])

    emit('eventNameXxx')
</script>

整合示例

子组件 RSC.vue

<script setup>
    defineProps(["data"])
    const emit = defineEmits(["delData"])
    function deleteData(item){
        emit("delData", item)
    }
</script>

<template>
    <div class="rsc">
       <table>
            <tr>
                <th>编号</th>
                <th>姓名</th>
                <th>年龄</th>
                <th>操作</th>
            </tr>
            <tr v-for="item in data" :key="item.sid">
                <td> {{ item.sid }}</td>
                <td> {{ item.name }}</td>
                <td> {{ item.age }}</td>
                <td>  <button @click="deleteData(item)">删除</button> </td>
            </tr>
       </table>
    </div>
</template>

父组件 RFC.vue

<script setup>

    import RSC from './RSC.vue';
    import {ref} from "vue"

    const data = ref([
        {sid: "s01",name: "Tom",age: "23"},
        {sid: "s02",name: "Jack",age: "24"},
        {sid: "s03",name: "Rose",age: "25"}
    ])


    function delDataAction(obj){
        const idx = data.value.indexOf(obj)
        data.value.splice(idx,1)
    }
</script>

<template>
    <RSC :data="data" @delData="delDataAction"  />
</template>

根组件App.vue

<script setup>
import RFC from './components/MyComponents/RFC.vue';
</script>

<template>
    <RFC />
</template>

总结

  • 父子组件之间反向数据传递需要使用事件监听实现
  • $emit() 方法只能在内联事件处理器中使用
  • defintEmit() 函数用来声明注册需要触发的事件名列表,并返回一个 emit 函数
  • defintEmit() 函数返回的 emit 函数可以在 <script setup>中触发事件
  • defintEmit() 函数只能在 <script setup>中使用,且不需要导入