【问题标题】:How to load data asynchronously inside App.vue during startup before rendering the router-view?在渲染路由器视图之前,如何在启动期间在 App.vue 中异步加载数据?
【发布时间】:2022-06-15 14:20:27
【问题描述】:

我通过npm init vue@latest 使用路由器项目设置了一个新的 Vue。在渲染router-view 之前,我必须异步加载一些数据并将其作为道具传递给router-view

App.vue 文件更改为

<script setup lang="ts">
import { RouterView } from "vue-router";

const response = await fetch("https://dummy.restapiexample.com/api/v1/employees");
const employees = await response.json();
</script>

<template>
  <router-view :employees="employees" />
</template>

不会呈现当前的路由器视图并出现警告

[Vue warn]: Component <Anonymous>: setup function returned a promise, but no <Suspense> boundary was found in the parent component tree. A component with async setup() must be nested in a <Suspense> in order to be rendered. 
  at <App>

但是我的 App.vue 文件没有任何父文件,所以我不能将它包装在 suspense 标记中。但是如何在渲染视图之前获取一些数据呢? (如果某些事情失败了,可能会显示一个错误框)

我是否必须创建一个 NestedApp.vue 文件,只是为了将其包装在一个 suspense 标记中?

我必须想出这样的东西吗?

<script setup lang="ts">
import { RouterView } from "vue-router";
import { ref } from "vue";

const isLoading = ref(true);
const errorOccured = ref(false);
let employees = ref([]);

fetch("https://dummy.restapiexample.com/api/v1/employees")
  .then(async response => {
    employees = await response.json();
    isLoading.value = false;
  })
  .catch(() => {
    errorOccured.value = true;
    isLoading.value = false;
  });
</script>

<template>
  <div v-if="errorOccured">
    Something failed!
  </div>
  <div v-else-if="isLoading">
    Still loading!
  </div>
  <router-view v-else :employees="employees" />
</template>

作为旁注我想做的事:

应用程序必须以包含 base64 编码数据的 url 哈希开始,这是一个基本 url。在提取和解码之后,我必须在渲染路由器视图之前使用这个 url 获取一些数据。

那么也许这个设置代码有一些更好的地方?我考虑过 main.ts 文件,但如果出现问题,我可以在 App.vue 文件中显示一个错误警报框。

【问题讨论】:

  • “我是否必须创建一个 NestedApp.vue 文件,只是为了将它包装在一个 suspense 标记中?” - 是的。它们可以称为 AppContainer 和 App,或者其他任何方式。
  • 可以在异步created()中加载数据,然后使用v-if来阻止渲染dom。

标签: vue.js


【解决方案1】:

你可以在 async created() 中加载数据,然后使用 v-if 来阻止渲染 dom。 (您可以改为显示加载屏幕或微调器。)

new Vue({
  el: '#app',
  data: {
    isLoaded: false,
  },
  async created() {  
    // load data (async/await)...
    await new Promise(r => setTimeout(r, 2000)); // wait 2 sec...
 
    this.isLoaded = true;
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <div v-if="isLoaded">Loaded! -> show data</div>
  <div v-else>Loading...</div>
</div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-27
    • 1970-01-01
    • 1970-01-01
    • 2016-08-02
    • 2018-05-08
    • 2018-12-31
    • 1970-01-01
    相关资源
    最近更新 更多