【问题标题】:What is a suspensible component in Vue 3?Vue 3 中的可挂起组件是什么?
【发布时间】:2021-04-22 17:22:09
【问题描述】:

我正在阅读这篇文章:https://v3.vuejs.org/guide/component-dynamic-async.html#using-with-suspense

它指的是一个名为“suspensible”组件的概念。

我进行了研究,但找不到任何关于什么是所谓的“suspensible”组件的信息。

谁能解释它是什么?谢谢!

【问题讨论】:

    标签: vue.js vuejs3


    【解决方案1】:

    “Suspensible” 表示可替换为备用内容,而父 <Suspense> 解析在其 <template #default> 中找到的 async 子组件。

    这个概念是从 React 的 Suspense API 借来的。


    更详细地说,<Suspense> 是一个内置的 Vue 3 组件,它呈现 <template #fallback> 而不是 <template #default>,直到默认模板中的所有 async 子组件都被解析。

    为了suspensible,组件的渲染需要依赖于一个promise:

    • 使用() => import('some/path')加载
    • 或在其setup 函数中使用async/await(或任何其他形式的Promise 语法)

    当包含在<Suspense> 的默认模板中时,一个可暂停组件被暂停,而其父 <Suspense> 尚未解析其所有可暂停组件,即使已暂停组件本身已解析.

    显然,<Suspense> 组件本身是可悬挂的,并且可以嵌套悬挂。


    这是 Vue 3 中 <Suspense> 上的 more detailed explanation


    在其他用法中,<Suspence> 提供了一种优雅而直观的方法来解决必须将子组件和模板包装在 v-if 中以防止尚未加载的数据的不存在属性的常见问题。

    一个典型的 Vue 2 示例:

    Vue.config.devtools = false;
    Vue.config.productionTip = false;
    
    Vue.component('render-items', {
      props: ['items'],
      template: `<table>
      <tr>
        <th>Id</th>
        <th>User Id</th>
        <th>Title</th>
      </tr>
      <tr v-for="(item, key) in items" :key="key">
        <td v-text="item.id"></td>
        <td v-text="item.userId"></td>
        <td v-text="item.title"></td>
      </tr>
    </table>`  
    });
    
    new Vue({
      el: '#app',
      data: () => ({
        items: []
      }),
      computed: {
        hasData() {
          return this.items.length;
        }
      },  
      async created() {
        const items = await fetch('https://jsonplaceholder.typicode.com/posts')
          .then(r => r.json());
        this.items = items;
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.12/vue.js"></script>
    <div id="app">
      <render-items :items="items" v-if="hasData"></render-items>
      <template v-else>loading...</template>
    </div>

    Vue 3 中的相同示例(或多或少),使用 &lt;Suspense&gt;async setup

    const RenderItems = Vue.defineComponent({
      async setup() {
        const items = await fetch('https://jsonplaceholder.typicode.com/posts')
          .then(r => r.json());
        return Vue.reactive({ items });
      },
      template: `<table>
      <tr>
        <th>Id</th>
        <th>User Id</th>
        <th>Title</th>
      </tr>
      <tr v-for="(item, key) in items" :key="key">
        <td v-text="item.id"></td>
        <td v-text="item.userId"></td>
        <td v-text="item.title"></td>
      </tr>
    </table>`
    });
    const App = { components: { RenderItems }};
    Vue.createApp(App).mount('#app');
    <script src="https://unpkg.com/vue@next/dist/vue.global.prod.js"></script>
    <div id="app">
      <Suspense>
        <template #default>
          <render-items></render-items>
        </template>
        <template #fallback>
          loading...
        </template>
      </Suspense>
    </div>

    一个主要优点是在 Vue 3 示例中,我们可以在子组件中包含数据获取器(和数据)。这在 Vue 2 中是不可能的,因为:

    • 只有在加载数据后才创建子组件
    • 父组件需要知道条件何时发生变化(因此它需要访问实际条件)才能在渲染后备内容或子组件之间切换。

    在 Vue 2 中最简单的方法实际上是在父组件中加载数据并通过 props 将结果传递给子组件。如果您有很多子组件,这种模式可能会变得混乱。

    在 Vue 3 中,加载数据和检查条件的责任完全由子组件负责。父母不需要访问实际情况。

    就像&lt;template&gt;&lt;Suspense&gt; 不会创建 DOM 元素。

    在上面的 Vue 3 示例中,&lt;RenderItems /&gt; 是可暂停的。

    【讨论】:

      【解决方案2】:

      一个可以使用 Vue 3 中的新项目的可暂停组件。一个可加载且可能需要较长时间才能加载的项目,例如 API 调用。通常,您会在悬念项目内的项目内使用 async/await。

      这里有很多很好的信息:https://v3.vuejs.org/guide/component-dynamic-async.html#async-components

      您可以使用悬念项目来表示,当悬念项目内的项目正在等待时显示其他内容(如骨架加载器)。

      【讨论】:

        猜你喜欢
        • 2021-05-08
        • 2021-02-24
        • 2021-10-22
        • 2021-12-31
        • 1970-01-01
        • 1970-01-01
        • 2021-06-09
        • 2011-12-22
        • 2021-01-15
        相关资源
        最近更新 更多