Vue页面中如何从添加组件触发列表组件刷新?可借助VueUse?
解决方案:Foo添加条目后触发Bar刷新列表
针对你这个场景,有几种可行的实现方案,包括常规Vue组件通信方式,以及用VueUse简化开发的方法,下面逐一说明:
一、常规Vue组件通信方案(父组件中转)
因为Foo和Bar都挂载在index.vue下,最直接的方式是通过父组件作为中间层传递刷新信号:
1. 修改Foo组件:添加成功后触发事件
<template> <h1>ADD NEW ITEM</h1> <v-text-field v-model="name" label="Name" type="text" @click:append="add" ></v-text-field> </template> <script setup> import { ref } from 'vue' // 定义要触发的事件 const emit = defineEmits(['itemAdded']) const name = ref('') async function add() { const res = await useFetch( "http://api.test/add", { method: "POST", query: { name: name.value, // 注意取ref的value值 }, } ) // 确认请求成功后通知父组件 if (res.status.value === 'success') { emit('itemAdded') name.value = '' // 清空输入框 } } </script>
2. 修改Bar组件:封装刷新方法并暴露给父组件
<template> <h1>LIST</h1> <v-data-table v-if="mydata" :headers="headers" :items="mydata.data" > </v-data-table> </template> <script setup> import { reactive } from 'vue' // 解构出useFetch的refetch刷新方法 const { data: mydata, refetch } = await useFetch( "http://api.test/list", { transform(data) { return JSON.parse(data); }, pick: ["data"], } ) // 把刷新方法暴露给父组件调用 defineExpose({ refreshList: refetch }) const headers = reactive([ { title: "ID", key: "id" }, { title: "Nom", key: "name" }, { title: "Création", key: "created_at" } ]) </script>
3. 修改index.vue:监听Foo事件,调用Bar的刷新方法
<template> <Foo @item-added="handleItemAdded" /> <Bar ref="barRef" /> </template> <script setup> import { ref } from 'vue' const barRef = ref(null) const handleItemAdded = () => { // 调用Bar组件暴露的刷新方法 barRef.value?.refreshList() } </script>
二、用VueUse实现(推荐)
VueUse提供了专门的工具可以简化组件间通信和状态监听,这里推荐两种方式:
方法1:使用useEventBus(事件总线)
useEventBus可以创建全局事件总线,跳过父组件直接在Foo和Bar之间传递信号:
1. 创建全局事件总线实例
新建utils/eventBus.js文件:
import { useEventBus } from '@vueuse/core' // 创建名为itemAdded的事件总线 export const itemAddedBus = useEventBus('itemAdded')
2. 修改Foo组件:发布事件
<template> <h1>ADD NEW ITEM</h1> <v-text-field v-model="name" label="Name" type="text" @click:append="add" ></v-text-field> </template> <script setup> import { ref } from 'vue' import { itemAddedBus } from '../utils/eventBus' const name = ref('') async function add() { const res = await useFetch( "http://api.test/add", { method: "POST", query: { name: name.value, }, } ) if (res.status.value === 'success') { // 发布刷新事件 itemAddedBus.emit() name.value = '' } } </script>
3. 修改Bar组件:订阅事件触发刷新
<template> <h1>LIST</h1> <v-data-table v-if="mydata" :headers="headers" :items="mydata.data" > </v-data-table> </template> <script setup> import { reactive, onMounted, onUnmounted } from 'vue' import { itemAddedBus } from '../utils/eventBus' const { data: mydata, refetch } = await useFetch( "http://api.test/list", { transform(data) { return JSON.parse(data); }, pick: ["data"], } ) // 订阅事件,组件挂载时监听 onMounted(() => { const unsubscribe = itemAddedBus.on(() => { refetch() }) // 组件销毁时取消订阅,避免内存泄漏 onUnmounted(unsubscribe) }) const headers = reactive([ { title: "ID", key: "id" }, { title: "Nom", key: "name" }, { title: "Création", key: "created_at" } ]) </script>
方法2:使用useSignal(信号量监听)
用useSignal创建一个全局信号量,Foo修改信号量状态,Bar监听状态变化触发刷新:
1. 创建全局信号量
新建utils/signals.js文件:
import { useSignal } from '@vueuse/core' // 创建用于触发列表刷新的信号量 export const refreshListSignal = useSignal(false)
2. Foo组件:修改信号量状态
// 在add函数成功后添加 refreshListSignal.value = !refreshListSignal.value
3. Bar组件:监听信号量变化
import { watch } from 'vue' import { refreshListSignal } from '../utils/signals' // 监听信号量变化,触发刷新 watch(refreshListSignal, () => { refetch() })
三、注意事项
- 必须确保API请求确实成功后再触发刷新,避免无效操作
- 使用事件总线或信号量时,记得在组件销毁时取消监听,防止内存泄漏
- 使用VueUse前需先安装:
npm i @vueuse/core
内容的提问来源于stack exchange,提问作者DevonDahon
相关产品推荐
相关产品推荐

