javascript - 如何在 Vue.js 中加载数据之前延迟“未找到”错误
问题描述
我正在走这条路:http://site.dev/person/1
我的组件看起来像这样:
// PeopleComponent.vue
<template>
<div>
<template v-if="person == null">
<b>Error, person does not exist.</b>
</template>
<template v-else>
<pre> {{ person }} </pre>
</template>
</div>
</template>
<script>
export default {
mounted() {
this.$store.dispatch('getPeople');
}
computed: {
// represents the person whose id potentially matches the value of `/:id` in route.
person(){
let id = parseInt(this.$route.params.id)
let person = null
if(id > 0)
person = this.$store.state.people.find(p => p.id == id)
return person;
}
}
}
</script>
// [styles]
我在这个组件中做什么:
我的 URL 中有一个 ID。ID 表示此页面上显示的特定资源。我有一个
person()
计算属性来从我的 Vuex 商店中检索其 ID 与 URL 中的参数匹配的对象。
期望的结果:
在页面顶部,如果找不到对象(例如,有人键入了在商店的对象数组中不存在的 ID),我想显示一条错误消息。如果找到该项目,则可以简单地转储该对象。这目前有效,但是从 API 获取数据和在存储中找到正确对象之间的延迟似乎刚刚足够长,以简要显示错误消息,就好像在页面首次加载时找不到对象一样。当使用较慢的网络速度进行测试时,此错误消息会显示几秒钟。我想消除它,如果对象存在,它根本不会出现。
我试过的:
v-cloak
- 尝试将此应用于每个父 div,甚至是其div#app
本身,但无济于事。我一定做错了什么。v-if
- 如上例所示
一些指点将不胜感激,谢谢!
2020 年 3 月 31 日更新
根据 Phil 的建议,我尝试加入一个标志来指示页面何时准备就绪。我以两种不同的方式做到了。
方法 #1
制作了mounted()
“异步”并在people
从我的 API 检索的操作上添加了等待。之后将标志设置为真:
async mounted() {
await this.$store.dispatch('getPeople');
this.loaded = true;
}
但我仍然简要地看到错误消息。
方法#2
在操作上使用then
回调,并将标志设置为true
回调内部
mounted() {
let vm = this
vm.$store.dispatch('getPeople').then(() => {
vm.loaded = true;
})
}
这两种方法都不会阻止消息的出现。
我怀疑这是正在发生的事情:
核心规则
错误应该只显示如果
loaded=true
和person=null
- 页面加载,
loaded
是false
和person
是null
。错误不会显示。 - Page 进行调用以从 API 中获取人员。错误仍然没有显示。
- 调用后,
loaded
已设置为true
[此时,计算属性loaded
已解决true
且person
尚未解决,这就是我相信我看到错误的地方。] - Computed 属性在下一个报价时从存储中找到相关记录。
Person
不再是null
,因此错误消失了。
编辑 01/04/2020
回答菲尔的问题:What does your getPeople() action look like?
getPeople({ commit }) {
axios.get('/get/people')
.then(response => {
commit("getPeople", response.data);
})
.catch(error => {
console.log(error);
})
},
解决方案
听起来您还需要一种状态,例如loading。
getPeople
将您的操作更改为可组合的,即返回AxiosPromise
以便它等待异步任务完成...
getPeople ({ commit }) {
// make sure you return the promise
return axios.get('/get/people').then(response => {
commit("getPeople", response.data)
}).catch(error => {
console.error(error)
// also make sure you don't accidentally convert this to a successful response
return Promise.reject(error)
})
},
然后尝试这样的事情
export default {
data: () => ({ loading: true }),
async created () {
// "created" fires earlier than "mounted"
await this.$store.dispatch('getPeople')
this.loading = false
},
computed: {
// etc
}
}
现在您可以loading
在模板中使用
<div v-if="loading">Loading...</div>
<div v-else>
<!-- your "person" template stuff goes here -->
</div>
推荐阅读
- windows - 3D 查看器不自动显示纹理
- asp.net - Dim outFileCTL As IO.StreamWriter = My.Computer.FileSystem.OpenTextFileWriter(filename,False) 在 C# 中等效
- firebase - 我怎样才能找到firebase nuxt的其他方法?
- flutter - Riverpod 的 AsyncValue 的 when 方法的属性 loading: 和 error: does not work as official document
- embedded - 如何将 STM32f4 编程为 SPI 从设备
- javascript - pixi.js 中“PIXI.Texture.from()”和“new PIXI.Texture()”的区别
- python - 将现有列替换为多个列的相同条件
- javascript - 编写简单的 JavaScript 程序
- python - 如何按顺序绘制计数器?
- r - 全年循环移动平均线