Vue 3组合式函数间如何通信?求最佳实现方案
Vue组合式函数间通信的最佳实践
问题背景
在Vue应用中,使用useUsers和useStatistics两个组合式函数时,需要在useStatistics的loadStatistics方法中修改useUsers内部的selectedUser ref变量,但由于作用域限制无法直接访问,以下是几种最佳实践方案。
方案1:直接传入目标Ref变量
将需要修改的selectedUser ref作为参数传递给useStatistics,让其内部方法直接操作ref的value属性,这是最直接的方式。
修改后的代码:
ShowStatistics.vue
<template> <select v-model="selectedUser"> <option v-for="user in users" :key="user.id" :value="user"> {{ user.name }} </option> </select> <button @click="loadStatistics"> Load Statistics </button> </template> <script setup lang="ts"> import { useUsers, useStatistics } from './composables' const { users, selectedUser } = useUsers() // 把selectedUser传入useStatistics const { loadStatistics } = useStatistics(selectedUser) </script>
useStatistics.ts
import type { Ref } from 'vue' export function useStatistics(selectedUser: Ref<any>) { const loadStatistics = () => { const statistics = StatisticsApi.loadStatistics() window.store.statistics = statistics // 直接修改ref的value selectedUser.value = statistics.user } return { loadStatistics } }
方案2:封装修改方法到源组合式函数
在useUsers内部封装修改selectedUser的方法,只暴露方法给外部调用,保持数据的封装性,避免外部直接操作内部状态,符合单一职责原则。
修改后的代码:
useUsers.ts
import { ref } from 'vue' export function useUsers() { const users = ref([]) const selectedUser = ref({}) users.value = UsersApi.getUsers() // 封装修改选中用户的方法 const setSelectedUser = (user: any) => { selectedUser.value = user } return { users, selectedUser, setSelectedUser } }
ShowStatistics.vue
<template> <select v-model="selectedUser"> <option v-for="user in users" :key="user.id" :value="user"> {{ user.name }} </option> </select> <button @click="loadStatistics"> Load Statistics </button> </template> <script setup lang="ts"> import { useUsers, useStatistics } from './composables' const { users, selectedUser, setSelectedUser } = useUsers() // 传入修改方法到useStatistics const { loadStatistics } = useStatistics(setSelectedUser) </script>
useStatistics.ts
export function useStatistics(setSelectedUser: (user: any) => void) { const loadStatistics = () => { const statistics = StatisticsApi.loadStatistics() window.store.statistics = statistics // 调用传入的方法修改选中用户 setSelectedUser(statistics.user) } return { loadStatistics } }
方案3:使用全局状态管理(如Pinia)
如果selectedUser是多个组件或组合式函数需要共享的状态,推荐使用全局状态管理工具(如Pinia),将状态抽离到全局store中,所有相关逻辑都通过store操作状态。
修改后的代码:
stores/userStore.ts
import { defineStore } from 'pinia' import { ref } from 'vue' export const useUserStore = defineStore('user', () => { const users = ref([]) const selectedUser = ref({}) // 获取用户列表的方法 const fetchUsers = () => { users.value = UsersApi.getUsers() } // 修改选中用户的方法 const setSelectedUser = (user: any) => { selectedUser.value = user } return { users, selectedUser, fetchUsers, setSelectedUser } })
useUsers.ts
import { useUserStore } from '../stores/userStore' export function useUsers() { const userStore = useUserStore() // 初始化用户数据 userStore.fetchUsers() return { users: userStore.users, selectedUser: userStore.selectedUser, setSelectedUser: userStore.setSelectedUser } }
useStatistics.ts
import { useUserStore } from '../stores/userStore' export function useStatistics() { const userStore = useUserStore() const loadStatistics = () => { const statistics = StatisticsApi.loadStatistics() window.store.statistics = statistics // 通过store修改选中用户 userStore.setSelectedUser(statistics.user) } return { loadStatistics } }
内容的提问来源于stack exchange,提问作者Martin Zeltin
相关产品推荐
相关产品推荐

