Vue.js中父组件Home.vue如何获取子组件LoggedUser的scope值
解决方案
你现在遇到的核心问题是用户权限数据散落在子组件里,跨组件层级访问耦合度高、维护麻烦,最合理的实现方式是抽离共享状态,从根源上避免跨组件传值的烂代码。
最优方案:抽离共享用户状态(推荐)
不要把用户信息请求逻辑写在单个展示组件里,把用户信息、接口请求逻辑抽成模块级别的可复用逻辑,所有用到用户信息的组件直接引入即可,不会重复发请求,也不受组件嵌套层级限制。
- 新建
src/composables/useLoggedUser.ts文件,存放全局共享的用户状态和请求逻辑:import { ref, onMounted } from 'vue' // 模块级响应式变量,所有引入该文件的组件共享同一份数据 const message = ref('You are not logged in!') const scope = ref('') const isLoaded = ref(false) export function useLoggedUser() { // 仅在第一次调用时触发接口请求,避免重复调用接口浪费资源 if (!isLoaded.value) { isLoaded.value = true onMounted(async () => { // 记得把这里写死的??替换成你实际存储的token值 let token = '??' const response = await fetch('https://localhost:44391/api/Auth/User', { headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, credentials: 'include' }) const content = await response.json() message.value = `Hi ${content.name}` scope.value = `${content.scope}` }) } return { message, scope } } - 改造原有
LoggedUser.vue组件,直接复用抽离的逻辑,不需要再单独写请求:<template> {{ message }} </template> <script lang="ts"> import { useLoggedUser } from '@/composables/useLoggedUser' export default { name: "LoggedUser", setup() { const { message } = useLoggedUser() return { message } } } </script> - 在
Home.vue里直接引入共享逻辑拿scope值,适配你现有的选项式API写法即可:import axios from 'axios' import SearchBar from './SearchBar.vue' import SideBar from './SideBar.vue' import LoggedUser from './LoggedUser.vue' // 引入共享用户逻辑 import { useLoggedUser } from '@/composables/useLoggedUser' import swal from 'sweetalert'; import '@trevoreyre/autocomplete-vue/dist/style.css' export default { name: "Home", components: { SearchBar, SideBar, LoggedUser }, // 用setup把共享的scope暴露给选项式实例 setup() { const { scope } = useLoggedUser() return { scope } }, data() { return { countries: [], showGrid: true, userScope: '' } }, watch: { // 监听scope加载完成,拿到值后再拉取国家数据做权限过滤 scope(newVal) { if (newVal) { this.userScope = newVal this.getCountries() } } }, methods: { getCountries() { let country = this.$route.query.query const reqUrl = country ? `https://localhost:44391/api/Pho/GetCountries?country=${country}` : "https://localhost:44391/api/Pho/GetCountries" axios.get(reqUrl).then(res => { // 直接在这里做权限匹配过滤,只返回当前用户权限范围内的国家 this.countries = res.data.filter(item => item.scope === this.userScope) }) if (country) this.searchbar = false }, }, mounted() { // 页面挂载时如果scope已经加载完成直接拉数据,否则等watch触发即可 if (this.scope) this.getCountries() } }
不推荐的临时方案(仅适合极小项目凑合用)
如果你不想改动现有组件结构,可以选以下两种方式,但长期维护会非常麻烦:
- 组件Ref取值:在Home模板中渲染LoggedUser组件并绑定ref,等子组件挂载完成后通过
this.$refs.xxx.scope取值。但你现在LoggedUser是嵌套在SideBar内部的,需要逐层找组件实例,嵌套层级深了代码根本没法维护,还会重复触发用户信息接口。 - 全局事件总线:引入mitt之类的事件库,LoggedUser拿到scope后触发全局事件传值,Home监听对应事件取值。项目大了之后事件来源、触发时机根本没法追溯,调试成本极高。
额外提醒:你现有代码里的token是写死的
??,记得替换成本地存储的真实登录token,同时给接口请求加错误捕获,避免接口报错导致页面白屏。
内容的提问来源于stack exchange,提问作者Nesrine Missaoui
相关产品推荐
相关产品推荐

