Vue.js 2中如何等待某一视图执行完毕后再执行其他视图
解决方案
核心思路
把全局数据的加载逻辑迁移到Vuex的Action中,通过Promise统一管理加载状态,确保依赖该数据的页面能等待数据加载完成后再执行后续逻辑。同时避免重复请求,保证多页面状态一致。
步骤1:重构Vuex Store,封装数据加载逻辑
将data_period的请求、状态管理统一放到Vuex模块中,返回Promise供外部等待:
// store/modules/dataPeriod.js const state = { items: [], itemData: null, isLoading: false, hasError: false, loadPromise: null // 缓存请求Promise,防止重复请求 }; const mutations = { SET_ITEMS(state, items) { state.items = items; }, SET_ITEM_DATA(state, data) { state.itemData = data; }, SET_LOADING(state, status) { state.isLoading = status; }, SET_ERROR(state, status) { state.hasError = status; }, SET_LOAD_PROMISE(state, promise) { state.loadPromise = promise; } }; const actions = { fetchDataPeriod({ commit, state }) { // 已在加载或加载完成,直接返回现有Promise if (state.isLoading || state.loadPromise) { return state.loadPromise; } const promise = this._vm.$http.get(`${process.env.VUE_APP_API_URL}/data_period`) .then(response => { commit('SET_ITEMS', response.data); commit('SET_ITEM_DATA', response.data[0].data); return response.data; }) .catch(() => { commit('SET_ERROR', true); throw new Error('数据周期加载失败'); }) .finally(() => { commit('SET_LOADING', false); }); commit('SET_LOADING', true); commit('SET_LOAD_PROMISE', promise); return promise; } }; const getters = { itemData: state => state.itemData, dataPeriodItems: state => state.items, isDataPeriodLoading: state => state.isLoading, hasDataPeriodError: state => state.hasError }; export default { namespaced: true, state, mutations, actions, getters };
步骤2:修改CurrentData组件,依赖Vuex状态
组件不再自行处理请求,改为调用Vuex Action,并从Store同步状态:
<script> import { Component, Vue } from 'vue-property-decorator'; import { mapState, mapActions, mapGetters } from 'vuex'; @Component({ computed: { ...mapState('dataPeriod', ['items']), ...mapGetters('dataPeriod', ['isDataPeriodLoading', 'hasDataPeriodError']) }, methods: { ...mapActions('dataPeriod', ['fetchDataPeriod']) } }) export default class CurrentData extends Vue { currentDataPeriod = ''; mounted() { this.fetchDataPeriod().then(items => { this.currentDataPeriod = items[0].data; }); } setCurrentDataPeriod(item) { this.$store.commit('dataPeriod/SET_ITEM_DATA', item.data); this.currentDataPeriod = item.data; } } </script>
步骤3:修改ItemData组件,等待数据加载完成
使用async/await等待Vuex Action完成后,再执行业务请求:
<script> import { Component, Vue } from 'vue-property-decorator'; import { mapGetters, mapActions } from 'vuex'; @Component({ computed: { ...mapGetters('dataPeriod', ['itemData']) }, methods: { ...mapActions('dataPeriod', ['fetchDataPeriod']) } }) export default class ItemData extends Vue { items = []; async mounted() { try { // 等待全局数据加载完成 await this.fetchDataPeriod(); this.getRandomData(); } catch (error) { console.error('全局数据加载失败:', error); // 可添加错误提示逻辑 } } getRandomData() { this.$http.get(`${process.env.VUE_APP_API_URL}/random`, { params: { itemData: this.itemData } }).then(response => { this.items = response.data; }).catch(error => { console.log(error); }); } } </script>
可选:全局路由守卫统一处理
如果多个页面都依赖该全局数据,可以通过路由守卫统一拦截,避免每个页面重复写等待逻辑:
// router/index.js import Vue from 'vue'; import Router from 'vue-router'; import store from '../store'; Vue.use(Router); const router = new Router({ routes: [ { path: '/item-data', name: 'ItemData', component: () => import('../views/ItemData.vue'), meta: { requiresDataPeriod: true } // 标记需要加载全局数据的页面 }, // 其他路由配置... ] }); router.beforeEach(async (to, from, next) => { if (to.matched.some(record => record.meta.requiresDataPeriod)) { try { await store.dispatch('dataPeriod/fetchDataPeriod'); next(); } catch (error) { // 加载失败时的处理,比如跳转到错误页 next(false); } } else { next(); } }); export default router;
内容的提问来源于stack exchange,提问作者mp252
相关产品推荐
相关产品推荐

