vue3.0 Suspense悬挂异步组件、定义异步组件

1、导入异步组件
	方式一:
		若组件setup返回的是一个Promise对象,则该组件默认为异步组件,导入时使用defineAsyncComponent异步导入/import同步导入都行

	方式二:
		手动定义异步组件并导入
		方式一:
			const Hel=defineAsyncComponent(()=> import('./components/HelloWorld.vue'))
			在components中配置
	    方式二:
	    	比如setup中返回一个Promise,则表明该组件就是一个异步组件
			  setup(){
			    return new Promise((resolve,reject)=>{
			      setTimeout(()=>{
			        resolve({
			          msg:'异步'
			        })
			      },2000)
			    })
			  }
			  async setup(){
			  	return {...}
			  }
		方式三:
			const AsyncComp = defineAsyncComponent(
			  () =>
			    new Promise((resolve, reject) => {
			      resolve({
			        template: '<div>I am async!</div>'
			      })
			      resolve(组件实例)
			    })
			 )

2、使用Suspense悬挂,当异步组件加载完成时,将展示设置的同步内容
	异步组件不需要作为 <suspense> 的直接子节点,它可以出现在组件树任意深度的位置,只有所有的后代组件都准备就绪,该内容才会被认为解析完毕。
	
	(1)使用:
		 <Suspense>
		 
		 异步内容:
			  方式一:
			      <template v-slot:default 简写#default>
			        <异步组件 />  
			      </template>
		      方式二:
		      	<component :is="Component"></component>
		      
		      方式三:
		      	<Dashboard /> 异步组件
	      
	      同步内容:
		      <template v-slot:fallback 简写#fallback>
				...同步展示内容
		      </template>
	      
	    </Suspense>
	    
	    另一个触发fallback的方式是让后代组件从setup函数中返回一个Promise
	 	export default {
		  async setup() {
		    在`setup`内部使用`await`需要非常小心
		    因为大多数组合式API函数只会在第一个`await`之前工作
		    const data = await loadData()
		
		    // 它隐性地包裹在一个 Promise 内
		    // 因为函数是 `async` 的
		    return {
		      // ...
		    }
		  }
		}
	
	(2)子组件更新展示fallback时机
		一旦<suspense>的default插槽里的内容被解析,则它只有在default根结点被替换的时候才能被再次触发。
		而树里的深层嵌套组件不足以让 <suspense> 回到等待状态
		
		如果根结点发生了变化,它会触发pending事件。
		默认情况下,它不会更新DOM以展示fallback内容,会继续展示旧的DOM,直到新组件准备就绪。
		
		给Suspense组件属性timeout,这个值是一个毫秒数,告诉 <suspense> 组件多久之后展示fallback,如果为0则表示它在 <suspense> 进入等待状态时会立即显示

 	(3)事件
 		pending:首次渲染、根结点发生了变化,
 		resolve:在default插槽完成新内容的解析之后被触发
 		fallback:在fallback插槽的内容展示的时候被触发
 	
 	(4)错误捕捉
 		errorCaptured 选项
 		onErrorCaptured() 钩子
 	
 	(5)和其他内置组件结合
 		<RouterView v-slot="{ Component }">
		  <template v-if="Component">
		    <Transition mode="out-in">
		      <KeepAlive>
		        <Suspense>
		          <!-- 主要内容 -->
		          <component :is="Component"></component>
		
		          <!-- 加载中状态 -->
		          <template #fallback>
		            正在加载...
		          </template>
		        </Suspense>
		      </KeepAlive>
		    </Transition>
		  </template>
		</RouterView>

代码示例:
异步组件:

<template>
  <!-- 不用写根标签 -->
  <div>{{msg}}</div>
  
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({  //定义一个组件
  name: 'AsyncHelloWorld',
  props: { //传递参数,可以添加类型约束
    msg: String,
  },
  setup(){
    return new Promise((resolve,reject)=>{
      setTimeout(()=>{
        resolve({
          msg:'异步'
        })
      },2000)
    })
  }
});
</script>

悬挂使用:

<template>
  <div id="nav">

    <Suspense>
      <template v-slot:default>
          
        <Hel />  
      </template>
      <template v-slot:fallback>
        <div>
          loading
        </div>
      </template>
      
    </Suspense>

  </div>
  <!-- <router-view/> -->
</template>

<script lang='ts'>
// ,ref, reactive
import {defineComponent,ref,reactive,onMounted,watch,shallowRef,shallowReadonly,defineAsyncComponent} from 'vue';
// import Hel from './components/HelloWorld.vue';
const Hel=defineAsyncComponent(()=> import('./components/HelloWorld.vue'));

export default defineComponent({
  name:"App",
  components:{
    Hel,
  }
})

</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值