我有Vue.js应用程序,它使用Axios从API获取一些复杂的数据,然后可视化这些数据。 我的代码如下所示:
{
data: () => ({
data: null, // or Object, it doesn't matter now
loading: false,
errored: false,
loadingMessage: ''
}),
methods: {
loadData: function() {
this.loading = true;
this.loadingMessage = 'Fetching Data';
axios.get('api/url/').then((response) => {
this.data= response.data; // or this.$set(this, 'data', response.data), it doesn't matter now
this.loadingMessage = 'Process Data';
this.processData();
})
.catch(function () {
this.errored= true;
})
.then(function () {
this.loading = false;
})
},
processData: function() {
// process data
}
}
}
然后我点击模板中的按钮,这个按钮调用loadData()
函数。 它工作正常,但是获取数据需要一些时间,处理也需要一些时间,Vue 仅在 axios 请求完成后更改模板和变量。所以我只看到Fetching Data
消息,但没有看到Process Data
.
如何向用户显示现在处理数据的哪个阶段? 也许我应该在watch methods
中调用processData()
函数,但这对我来说似乎有点过分了。
更新
我最终得到了setTimeout()
包装。请参阅下面的答案。
Vue 有一个名为nextTick
的函数,这是一个异步函数,基本上意味着"在下一次视觉更新后执行以下代码"。如果我有这样的视觉更新,我通常会使用此方法。
我认为您的示例中的代码如下所示:
axios
.get('api/url/')
.then((response) => {
this.data= response.data;
this.loadingMessage = 'Process Data';
return this.$nextTick();
})
.then(() => {
this.processData();
})
.catch (etc ...
我不完全确定。我通常在支持 webpack/babel 的环境中工作,在这种情况下,我只会让整个函数async
并编写:
async function fn() {
const response = await axios.get('api/url/');
this.data = response.data;
this.loadingMessage = 'Process Data';
await this.$nextTick();
this.processData();
}
你可以在这里阅读它(https://v2.vuejs.org/v2/guide/reactivity.html#Async-Update-Queue(
您可以尝试按如下方式更改函数吗:
loadData: function() {
this.loading = true;
this.loadingMessage = 'Fetching Data';
axios.get('api/url/').then((response) => {
this.data= response.data; // or this.$set(this, 'data', response.data), it doesn't matter now
this.$nextTick(() => {
this.loadingMessage = 'Process Data';
this.processData();
})
})
.catch(function () {
this.errored= true;
})
.then(function () {
this.loading = false;
})
},
我尝试使用$nextTick()
,正如@joachim-bøggild建议的那样。我甚至试图用$forceUpdate()
来拱起这个目标。但由于某种我不清楚的原因,我没有观察到我需要的效果。控制台显示值已更改。但是在屏幕和 Vue Devtools 中,旧结果会显示,直到请求完成。
所以我决定用一个例子来补充这个问题,并开始在 JsFiddle 上创建演示。为了显示我需要的渲染延迟,我使用了setTimeout(() =>{ this.loading = false}, 1000)
,完全没有问题。
我将这种方法移植到我的代码中,一切都运行良好。直到我试图删除这个setTimeout()
.问题又出现了。
因此,最终,我最终选择了这个代码设计:
...
axios.get('api/url/').then((response) => {
this.data= response.data;
this.loadingMessage = 'Process Data';
setTimeout(() => {
this.processData();
this.loading = false;
}, 10); // if this value less than 10 error still occurs
})
.catch(function () {
this.errored= true;
})
...
如果有人了解为什么会发生这种行为,请完成我的回答。