Vue中如何控制v-for渲染的单个组件加载状态不影响其他组件
问题原因
你给所有v-for渲染的子组件都绑定了同一个父组件下的布尔型loading变量,只要这个变量变为true,所有子组件接收到的loading属性都会同步生效,自然会全部切换为加载状态,无法区分具体哪个组件触发了请求。
修复方案
不要用单一布尔值存储全局加载状态,改为存储当前处于加载状态的子组件唯一标识(当前场景下可以直接用v-for的index作为子组件唯一标识),传给子组件的loading属性通过「当前子组件标识是否等于加载中标识」动态计算,即可实现仅点击的组件显示加载态。
具体代码修改
父组件 parentComponent.vue
- 将原有的
loading: false替换为activeLoadingIndex: null,用来存当前加载中的子组件index,null表示没有组件处于加载态 - 给子组件传props时,将
:loading="loading"改为:loading="activeLoadingIndex === index",只有当前遍历到的子组件index和激活加载的index匹配时,才会传入true - 点击事件处理逻辑中,先记录当前触发事件的子组件index,请求结束后重置
activeLoadingIndex为null
<template> <div> <childComponent v-for="(element, index) in 3" :key="index" :data="index" :loading="activeLoadingIndex === index" @click-from-child="clickedEvent" /> <p>{{ returnedData }}</p> </div> </template> <script> import childComponent from "./childComponent"; export default { components: { childComponent }, data() { return { activeLoadingIndex: null, returnedData: "", }; }, methods: { clickedEvent({ customURL, componentIndex }) { this.activeLoadingIndex = componentIndex; this.returnedData = ""; console.log(`Request Sent to: ${customURL}`); setTimeout(() => { console.log("Request Completed - Success"); this.returnedData = `Some Data returned from: ${customURL}`; this.activeLoadingIndex = null; }, 3000); }, }, }; </script>
子组件 childComponent.vue
触发事件时,把自身的index(存在props.data中)和请求参数一起传给父组件即可,模板部分不需要改动:
<template> <p v-if="loading">LOADING...</p> <p v-else @click="triggerMethod">Click Me</p> </template> <script> export default { props: { data: { type: Number, }, loading: { type: Boolean, default: false, }, }, methods: { triggerMethod() { const customURL = `getDataURL/data=${this.data}`; this.$emit("click-from-child", { customURL, componentIndex: this.data }); }, }, }; </script>
可选优化方案
如果不想让父组件管理子组件的加载状态,也可以把loading状态放在子组件内部维护:子组件点击时先自行切换为加载态,父组件请求完成后,通过ref或者事件通知对应子组件重置加载状态即可。这种方式适合子组件自身状态独立性较强的场景,当前逻辑用上述方案改动量最小。
内容的提问来源于stack exchange,提问作者babis95
相关产品推荐
相关产品推荐

