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失效原因分析
- 事件名格式不匹配:Vue3中emit的驼峰事件名会自动转为短横线格式,父组件需监听
group-created而非groupCreated; - 未正确定义emit:组件A未通过
defineEmits声明事件,或调用emit时事件名拼写错误; - 父组件未监听事件:父组件未在组件A标签上绑定对应的事件处理函数。
内容的提问来源于stack exchange,提问作者Jack88
相关产品推荐
相关产品推荐

