如何避免页面切换时Vue组件重复渲染?附异步处理场景问题
问题分析与解决方案
你的代码流程逻辑本身没问题,但重复渲染的根源在于状态更新的冗余操作和数组引用赋值导致的响应式追踪问题,以下是具体修复步骤:
1. 简化异步流程,避免冗余Promise包装
created钩子中无需额外包装Promise,直接复用dispatch返回的Promise即可,同时统一无token时的流程:
created() { // 用官方API判断模块是否存在,避免依赖内部属性 if (!this.$store.hasModule(STORE_ADMIN_AUTH_KEY)) { this.$store.registerModule(STORE_ADMIN_AUTH_KEY, store); } if (localStorage.getItem(ADMIN_AUTH_TOKEN_KEY)) { // 直接赋值dispatch的Promise,同时同步role到组件data this.isPending = this.$store.dispatch(STORE_ADMIN_AUTH_KEY + "/getInfo").then(data => { this.role = data.role || adminRole.OWNER; localStorage.setItem("AUTH", JSON.stringify(this.role)); }); } else { // 无token时给一个已resolve的Promise,保证mounted流程统一 this.isPending = Promise.resolve(); } },
2. 用计算属性替代手动赋值,减少状态更新
将dataSidebar改为计算属性,只有当role变化时才重新计算,避免手动修改数组导致的多次渲染:
// 移除data中的dataSidebar,添加computed属性 computed: { dataSidebar() { if (this.role === adminRole.OWNER) { // 用扩展运算符创建新数组,避免引用原数组引发意外更新 return [...sidebarItems]; } // 用filter生成新数组,替代forEach+push的冗余操作 return sidebarItems.filter(item => item.onlyOwner === 0); } },
3. 优化mounted逻辑
此时getSitebarItems可以直接删除,mounted只需等待异步完成即可(因为计算属性会自动依赖role变化更新):
async mounted() { await this.isPending; // 无需再调用getSitebarItems,计算属性已自动处理 },
4. 优化子组件渲染(可选)
如果Sidebar组件仍存在不必要的重渲染,可以在Sidebar组件中添加shouldComponentUpdate钩子(Vue2),仅当sidebar-data实际变化时才更新:
// Vue2 Sidebar组件示例 shouldComponentUpdate(nextProps) { // 对比数组内容是否变化,避免引用相同但内容不变时的重渲染 return JSON.stringify(nextProps.sidebarData) !== JSON.stringify(this.$props.sidebarData); }
核心原因说明
- 原代码中手动修改
dataSidebar数组(push/直接赋值引用),会触发Vue响应式系统多次更新; - 通过localStorage中转role状态,多了一次不必要的状态同步,可能引发额外渲染;
- 计算属性会缓存结果,只有依赖的
role变化时才重新计算,从根源减少渲染次数。
内容的提问来源于stack exchange,提问作者Duc Vo
相关产品推荐
相关产品推荐

