Skip to content

Suspense组件

1. 基本概念

1.1 什么是Suspense

Suspense是Vue3新增的内置组件,用于处理异步组件和异步数据加载的场景。它可以在等待异步内容加载完成时显示加载状态。

1.2 主要功能

  • 处理异步组件加载
  • 协调多个异步依赖
  • 提供加载状态管理
  • 错误处理机制

2. 基本用法

2.1 基础示例

vue
<template>
  <Suspense>
    <!-- 默认插槽:异步内容 -->
    <template #default>
      <async-component />
    </template>
    
    <!-- fallback插槽:加载状态 -->
    <template #fallback>
      <div>Loading...</div>
    </template>
  </Suspense>
</template>

2.2 异步组件定义

js
// AsyncComponent.vue
export default {
  async setup() {
    const data = await fetchData()
    return { data }
  }
}

// 使用defineAsyncComponent
const AsyncComp = defineAsyncComponent(() =>
  import('./components/AsyncComponent.vue')
)

3. 高级特性

3.1 多个异步依赖

vue
<template>
  <Suspense>
    <template #default>
      <div>
        <async-comp-1 />
        <async-comp-2 />
        <async-comp-3 />
      </div>
    </template>
    <template #fallback>
      <loading-component />
    </template>
  </Suspense>
</template>

3.2 错误处理

vue
<template>
  <Suspense>
    <template #default>
      <async-component />
    </template>
    <template #fallback>
      <loading-component />
    </template>
  </Suspense>
</template>

<script>
export default {
  errorCaptured(error) {
    // 处理加载错误
    console.error('Async component error:', error)
    return false // 阻止错误继续传播
  }
}
</script>

4. 实际应用场景

4.1 数据预加载

vue
<script setup>
async function setupComponent() {
  const userPromise = fetchUserData()
  const postsPromise = fetchUserPosts()
  
  const [user, posts] = await Promise.all([
    userPromise,
    postsPromise
  ])
  
  return { user, posts }
}
</script>

4.2 路由组件

js
// router.js
const routes = [
  {
    path: '/profile',
    component: () => import('./views/UserProfile.vue')
  }
]

5. 性能优化

5.1 延迟加载

js
const AsyncComponent = defineAsyncComponent({
  loader: () => import('./AsyncComponent.vue'),
  delay: 200, // 延迟显示加载状态
  timeout: 3000 // 超时时间
})

5.2 缓存策略

vue
<template>
  <keep-alive>
    <Suspense>
      <template #default>
        <async-component />
      </template>
    </Suspense>
  </keep-alive>
</template>

6. 最佳实践

6.1 组件设计

js
// 合理的异步组件设计
export default {
  async setup() {
    // 并行请求数据
    const [userData, preferences] = await Promise.all([
      fetchUserData(),
      fetchUserPreferences()
    ])
    
    // 数据处理
    const processedData = processUserData(userData)
    
    return {
      userData: processedData,
      preferences
    }
  }
}

6.2 加载状态处理

vue
<template>
  <Suspense>
    <template #default>
      <async-content />
    </template>
    <template #fallback>
      <div class="loading-container">
        <loading-spinner />
        <loading-progress :progress="loadingProgress" />
      </div>
    </template>
  </Suspense>
</template>

7. 注意事项

  1. 避免无限循环的异步依赖
  2. 合理设置超时时间
  3. 做好错误处理
  4. 考虑服务端渲染场景
  5. 优化加载体验

8. 与其他特性配合

8.1 与Transition配合

vue
<template>
  <Transition
    enter-active-class="fade-enter-active"
    leave-active-class="fade-leave-active"
  >
    <Suspense>
      <!-- 异步内容 -->
    </Suspense>
  </Transition>
</template>

8.2 与状态管理配合

js
// store.js
export const useLoadingStore = defineStore('loading', {
  state: () => ({
    isLoading: false,
    error: null
  }),
  actions: {
    startLoading() {
      this.isLoading = true
    },
    endLoading() {
      this.isLoading = false
    }
  }
})