You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue 3.2跨组件数据传递:如何无刷新刷新组件B?

Vue3.2 组件间数据刷新解决方案

问题背景

在Vue3.2项目中,CreateNewAccessGroupModal(组件A)提交POST请求创建权限组后,需要将响应的新组数据传递给AccessGroup(组件B),实现列表无刷新更新,尝试使用defineEmits未生效。组件结构为:父页面组件同时包含组件A和组件B。

解决方案一:父组件中转(最直接)

利用Vue的父子组件通信,通过组件A触发事件传递数据,父组件接收后更新状态,组件B通过props接收最新数据自动刷新。

1. 改造组件A(CreateNewAccessGroupModal)

定义emit事件,提交成功后触发事件传递新组数据:

<script setup>
import { ref } from "vue";
import axios from 'axios';

// 接收父组件传入的权限参数
const props = defineProps({
    permissions_param: Array,
});
// 声明要触发的自定义事件
const emit = defineEmits(['groupCreated']);

// 表单数据绑定
const group_name = ref('');
const description = ref('');
const permissions = ref([]);

async function createNewAccessGroup() {
    try {
        const response = await axios.post('你的创建组接口地址', {
            group_name: group_name.value,
            description: description.value,
            permissions: permissions.value
        });
        
        if (response.data.success) {
            // 触发事件,将新组数据传给父组件
            emit('groupCreated', response.data.data);
            // 手动关闭模态框(根据项目模态框实现调整)
            const modal = document.getElementById('modalCreateAccessNewGroup');
            modal.classList.remove('show');
            document.body.classList.remove('modal-open');
            document.querySelector('.modal-backdrop')?.remove();
        } else {
            alert(`创建失败:${response.data.message}`);
        }
    } catch (error) {
        console.error(error);
        alert('请求出错,请重试');
    }
}
</script>

2. 改造父页面组件

监听组件A的事件,更新自身的权限组列表,并传递给组件B:

<template>
    <MainLayout title="Access Groups" :sidebar="true">
        <!-- ... 原有头部、操作栏代码不变 ... -->
        <div class="main-body">
            <div class="table">
                <!-- ... 表格头部代码不变 ... -->
                <div class="table-body">
                    <div class="table-body__wrap">
                        <!-- 将权限组列表通过props传给组件B -->
                        <AccessGroup :access_groups="access_groups" />
                    </div>
                </div>
            </div>
        </div>
    </MainLayout>
    <!-- 监听组件A的groupCreated事件 -->
    <CreateNewAccessGroupModal 
        :permissions_param="permissions_param" 
        @group-created="handleGroupCreated"
    />
</template>

<script setup>
import { ref, onMounted } from "vue";
import axios from 'axios';
import AccessGroup from '@/Components/AccessGroup.vue';
import CreateNewAccessGroupModal from '@/Components/CreateNewAccessGroupModal.vue';

// 权限组列表(响应式)
const access_groups = ref([]);
const permissions_param = ref([]);

// 获取初始权限组列表
async function fetchAccessGroups() {
    const res = await axios.get('你的权限组列表接口');
    if (res.data.success) {
        access_groups.value = res.data.data;
    }
}

// 处理组件A传来的新组数据
function handleGroupCreated(newGroup) {
    // 将新组添加到列表开头(或末尾,根据需求调整)
    access_groups.value.unshift(newGroup);
    // 也可以重新调用fetchAccessGroups()获取完整最新列表
}

// 页面挂载时加载初始数据
onMounted(() => {
    fetchAccessGroups();
});
</script>

3. 组件B(AccessGroup)确保props接收正确

仅需补充props定义,模板无需修改:

<script setup>
// 接收父组件传入的权限组列表
defineProps({
    access_groups: {
        type: Array,
        required: true
    }
});
</script>

解决方案二:Pinia状态管理(适合复杂场景)

如果项目中有多个组件需要共享权限组数据,推荐使用Pinia做全局状态管理,无需依赖父组件中转。

1. 创建Pinia Store

新建stores/accessGroup.js:

import { defineStore } from 'pinia';
import axios from 'axios';

export const useAccessGroupStore = defineStore('accessGroup', {
    state: () => ({
        // 权限组列表状态
        accessGroups: []
    }),
    actions: {
        // 获取权限组列表
        async fetchGroups() {
            const res = await axios.get('你的权限组列表接口');
            if (res.data.success) {
                this.accessGroups = res.data.data;
            }
        },
        // 添加新组到列表
        addNewGroup(newGroup) {
            this.accessGroups.unshift(newGroup);
            // 若需要保证数据完全同步,可重新调用fetchGroups()
            // await this.fetchGroups();
        }
    }
});

2. 组件A中更新Store状态

<script setup>
import { ref } from "vue";
import axios from 'axios';
import { useAccessGroupStore } from '@/stores/accessGroup';

const props = defineProps({
    permissions_param: Array,
});
// 获取Store实例
const groupStore = useAccessGroupStore();

const group_name = ref('');
const description = ref('');
const permissions = ref([]);

async function createNewAccessGroup() {
    try {
        const response = await axios.post('你的创建组接口地址', {
            group_name: group_name.value,
            description: description.value,
            permissions: permissions.value
        });
        
        if (response.data.success) {
            // 调用Store的方法添加新组
            groupStore.addNewGroup(response.data.data);
            // 关闭模态框
            const modal = document.getElementById('modalCreateAccessNewGroup');
            modal.classList.remove('show');
            document.body.classList.remove('modal-open');
            document.querySelector('.modal-backdrop')?.remove();
        } else {
            alert(`创建失败:${response.data.message}`);
        }
    } catch (error) {
        console.error(error);
        alert('请求出错,请重试');
    }
}
</script>

3. 组件B中从Store获取数据

<template>
    <!-- 直接从Store中获取权限组列表 -->
    <div v-for="(access_group, index) in groupStore.accessGroups" :key="access_group.id" class="table-row">
        <!-- ... 原有模板内容不变 ... -->
    </div>
    <EditAccessGroupModal/>
    <ViewAccessGroupUsersModal/>
</template>

<script setup>
import { onMounted } from "vue";
import { useAccessGroupStore } from '@/stores/accessGroup';

const groupStore = useAccessGroupStore();

// 页面挂载时加载初始数据
onMounted(() => {
    groupStore.fetchGroups();
});
</script>

原defineEmits失效原因分析

  1. 事件名格式不匹配:Vue3中emit的驼峰事件名会自动转为短横线格式,父组件需监听group-created而非groupCreated;
  2. 未正确定义emit:组件A未通过defineEmits声明事件,或调用emit时事件名拼写错误;
  3. 父组件未监听事件:父组件未在组件A标签上绑定对应的事件处理函数。

内容的提问来源于stack exchange,提问作者Jack88

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 19:15:31