前端开发经常遇到异步的问题,请求函数,链接库,等,都有可能需要通过promise或者async await 来进行异步的一个封装。
异步组件也由此诞生,我用settimeout来模拟一个vue3的异步组件
异步的子组件
<template>
  <div>{{ someData }}</div>
</template>
<script lang="ts">
import { ref } from 'vue'
import { Data } from './types/index'
export default {
  setup(props: Data) {
    const someData = ref('dx')
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        return resolve({ someData })
      }, 3000)
    })
  }
}
</script>
按照正常组件使用
<template>
  <div class="about">
    <h1>This is an about page</h1>
    <Child />
  </div>
</template>
<script lang="ts">
import Child from '@/components/template/Template.vue'
export default {
  components: {
    Child
  }
}
</script>
页面会有警告,而且组件渲染也失败了,解析了警告的意思,是说这种异步组件需要一个Suspense来包裹一下
 
 Suspense 是vue3新增的一个内置组件,专门用来处理异步组件的。
异步组件的正确使用方式
<template>
  <div class="about">
    <h1>This is an about page</h1>
    <Suspense>
      <template v-slot:default>
        <Child />
      </template>
      <template v-slot:fallback>
        <h3>请稍等</h3>
      </template>
    </Suspense>
    <!-- <Child /> -->
  </div>
</template>
<script lang="ts">
import { defineAsyncComponent } from 'vue'
// import Child from '@/components/template/Template.vue'
const Child = defineAsyncComponent(() => import('@/components/template/Template.vue'))
export default {
  components: {
    Child
  }
}
</script>
Suspense的原理是通过插槽来实现的,一个default和一个fallback。
 default里面放置异步组件,fallback里面就放置异步组件未渲染之前的一个样式
有人说vue3中setup不能是异步函数,上面的代码证明,setup可以是异步函数,他们可能不了解Suspense这个内置组件。
async await 的setup函数
<template>
  <div>{{ someData }}</div>
</template>
<script lang="ts">
import { ref } from 'vue'
import { Data } from './types/index'
export default {
  async setup(props: Data) {
    const currentInstance: ComponentInternalInstance | null = getCurrentInstance()
    const someData = ref('dx')
    const result = await new Promise((resolve, reject) => {
      setTimeout(() => {
        return resolve({ someData })
      }, 3000)
    })
    return result
  }
}
</script>
父组件通过Suspense使用异步的子组件
<template>
  <div class="about">
    <h1>This is an about page</h1>
    <Suspense>
      <template v-slot:default>
        <Child />
      </template>
      <template v-slot:fallback>
        <h3>请稍等</h3>
      </template>
    </Suspense>
    <!-- <Child /> -->
  </div>
</template>
<script lang="ts">
import { defineAsyncComponent } from 'vue'
// import Child from '@/components/template/Template.vue'
const Child = defineAsyncComponent(() => import('@/components/template/Template.vue'))
export default {
  components: {
    Child
  }
}
</script>
最后总结一下,只要将异步组件放在suspense的default插槽中即可。



















