如何在 Vuex 操作完成之前阻止 Vue 生命周期继续进行?
Posted
技术标签:
【中文标题】如何在 Vuex 操作完成之前阻止 Vue 生命周期继续进行?【英文标题】:How to stop Vue life cycle from moving on before Vuex actions have completed? 【发布时间】:2019-11-16 22:13:03 【问题描述】:在我的应用程序中,我想在应用程序的其余部分启动之前初始化 3 个 Vuex 模块。但是,无论我尝试什么,我执行初始化的 Vue 实例生命周期钩子中的代码都会在 3 个模块完成初始化之前继续运行。
我在执行初始化的 Vuex 操作中的代码周围添加了一个承诺,以便我可以(a)等待调用生命周期钩子中的那些,但它不起作用。
我查看了使用 Axios 的示例 Vuex 代码,我必须使我的代码与此类似,但没有成功。
我尝试使用“Promise.all(...)”在“beforeCreate”生命周期挂钩中调用 init,但这仍然没有解决问题。
我的主 Vue 实例的代码如下所示:
new Vue(
router,
store,
async beforeCreate()
await this.$store.dispatch('init')
,
render: h => h(App)
).$mount('#app')
Vuex store 由 3 个模块组成,所有模块都有一个“init”动作。所有 3 个模块中的操作代码都是相同的。在下面的代码中有“XXX”的地方,每个模块的调用都会略有不同;
init: (commit, dispatch) =>
return new Promise((resolve, reject) =>
console.log('Start of init of XXX');
Axios.get(`api/xxx`).then(response =>
return response.data;
, error =>
console.log('An error occured: ', error);
reject(error);
).then(data =>
const result = [];
for (let key in data)
result.push(data[key]);
console.log('The API call resulted in ' + result.length + ' lines of code');
resolve(result);
commit('ADD_XXX', result);
)
)
我期望的是“beforeCreate”代码会一直等待,直到 3 个 init 操作调用完全完成(即,直到所有承诺都已实现)。
我看到的是操作已启动(我在控制台中看到“Start of init...”日志)。但随后我看到其中一个应用程序组件的mounted() 函数中的代码开始执行,它不应该执行,因为如果存储尚未完全初始化,它将无法正常工作。
【问题讨论】:
我认为您不应该在应用程序的引导部分执行此操作。只需在您的 api 调用待处理时显示“正在初始化...”页面或其他内容。顺便说一句,您的商店已初始化,您的 init api 调用正在等待中。 【参考方案1】:您不能暂停beforeCreate
,将其设为async
。当您点击await
时,它可能会在内部“暂停”,但从外部角度来看,它只是返回一个承诺。 Vue 不会注意到返回值,因此 Promise 将被忽略,并且生命周期将继续不间断。您可以做的是在您的 data
中添加一些状态并对其进行操作以达到所需的效果:
new Vue(
router,
store,
data ()
return
ready: false
,
async beforeCreate()
await this.$store.dispatch('init')
this.ready = true
,
render (h)
if (this.ready)
return h(App)
).$mount('#app')
顺便说一句,您不需要在 init
中创建新的 Promise,您只需返回由 axios 创建的链式 Promise。
更新:
这是另一种方式,只是不要打电话给mount
。
new Vue(
router,
store,
async beforeCreate()
await this.$store.dispatch('init')
this.$mount('#app')
,
render: h => h(App)
)
【讨论】:
并且 Vue 实例是否“知道”它必须一直等待直到“this.ready”(在渲染中)变为真,或者如果不是,则渲染会结束,而不是渲染有什么? 我的示例中的render
函数最初不会渲染任何内容,但当 ready
更改时它将再次运行。 render
函数的行为很像计算属性,当反应依赖发生变化时会重新运行。所有组件模板都编译为 render
函数,根 Vue 实例通常不使用模板的唯一原因是避免需要完整的 Vue 构建。您习惯的所有自动重新渲染反应性功能只是 render
幕后功能。以上是关于如何在 Vuex 操作完成之前阻止 Vue 生命周期继续进行?的主要内容,如果未能解决你的问题,请参考以下文章
vue-test-utils:如何在 mount() 生命周期钩子(使用 vuex)中测试逻辑?