• 【vue设计与实现】异步组件与函数式组件 2 - 超时与Error组件


    超时与Error组件

    在弱网环境下,加载一个组件可能需要很长时间,因此,要为用户提供指定超时时长的能力,当加载组件的时间超过了指定时长后,会触发超时错误。这时如果用户配置了Error组件,则会渲染该组件

    首先设计用户接口,为了让用户能够指定超时时长,defineAsyncComponent函数需要接受一个配置对象作为参数:

    const AsyncComp = defineAsyncComponent({
    	loader: ()=>import('CompA.vue'),
    	timeout: 2000, // 超时时长,其单位是ms
    	errorComponent: MyErrorComp // 指定出错时要渲染的组件
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5

    设计好用户接口后,就可以给出具体实现了,如下面代码所示:

    function defineAsyncComponent(options){
    	// options可以是配置项,也可以是加载器
    	if(typeof options = 'function'){
    		// 如果options是加载器,则将其格式化为配置项形式
    		options = {
    			loader: options
    		}
    	}
    	const {loader} = options
    	
    	let InnerComp = null
    	
    	return {
    		name: 'AsyncComponentWrapper',
    		setup(){
    			const loaded = ref(false)
    			// 代表是否超时,默认为false,即没有超时
    			const timeout = ref(false)
    			
    			loader().then(c => {
    				InnerComp = c;
    				loader.value = true
    			})
    			
    			let timer = null
    			if(option.timeout){
    				// 如果制定了超时时长,则开启一个定时器计时
    				timer = setTimeout(()=>{
    					// 超时后将 timeout 设置为true
    					timeout.value = true
    				}, options.timeout)
    			}
    			// 包装组件被卸载时清除定时器
    			onUnmounted(()=>{
    				clearTimeout(timer)
    			})
    			// 占位内容
    			const placeholder = {type:Text, children: ''}
    			return ()=>{
    				if(loaded.value){
    					return {type: InnerComp }
    				}else if(timeout.value){
    					// 如果加载超时,并且用户指定了Error组件,则渲染该组件
    					return options.errorComponent ? {type: options.errorComponent}: placeholder
    				}
    				return placeholder
    			}
    		}
    	}	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    要注意的点:

    1. 需要一个标志变量来标识是否已经超时
    2. 当包装组件被卸载时,需要清除定时器
    3. 根据loaded变量的值以及timeout变量的值来决定具体的渲染内容

    这样就实现了对加载超时的兼容,以及对Error组件的支持。除此之外,还要为用户提供以下能力:

    1. 当错误发生时,把错误对象作为Error组件的props传递过去,以便用户后续能自行进行更细粒度的处理
    2. 除了超时之外,还有有能力处理其他原因导致的加载错误,例如网络失败等

    对代码做如下调整:

    function defineAsyncComponent(options){
    	if(typeof options = 'function'){
    		options = {
    			loader: options
    		}
    	}
    	const {loader} = options
    	
    	let InnerComp = null
    	
    	return {
    		name: 'AsyncComponentWrapper',
    		setup(){
    			const loaded = ref(false)
    			// 定义error,当错误发生时,用来存储错误对象
    			const error = shallowRef(null)
    			
    			loader().then(c => {
    				InnerComp = c;
    				loader.value = true
    			})// 添加catch语句来捕获加载过程中的错误
    			.catch((err)=>{error.value = err})
    			
    			let timer = null
    			if(option.timeout){
    				// 如果制定了超时时长,则开启一个定时器计时
    				timer = setTimeout(()=>{
    					// 超时后创建一个错误对象,并复制给error.value
    					const err = new Error(`Async component timed out after ${options.timeout}ms.`)
    					error.value = err
    				}, options.timeout)
    			}
    			
    			// 包装组件被卸载时清除定时器
    			onUnmounted(()=>{
    				clearTimeout(timer)
    			})
    			// 占位内容
    			const placeholder = {type:Text, children: ''}
    			return ()=>{
    				if(loaded.value){
    					return {type: InnerComp }
    				}else if(error.value && options.errorComponent){
    					// 只有当错误存在且用户配置了errorComponent时才展示Error组件,同时将error作为props传递
    					return {type:options.errorComponent, props:{error:error.value}}
    				}
    				return placeholder
    			}
    		}
    	}	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    在组件渲染时,只要error.value的值存在,且用户配置了errorComponent组件,就直接渲染errorComponent组件并将error.value的值作为该组件的props传递,这样用户就可以在自己的Error组件上,通过定义名为error的props来接收错误对象,从而实现细粒度的控制

  • 相关阅读:
    python安装davisinteractive模块
    使用 Nginx 实现 URL 的重定向
    最长连续序列[中等]
    半球体容器漏水体积微分问题
    《零基础学机器学习》笔记-第3课-线性回归
    ICPC2023合肥站:D. Balanced Array
    网络安全(黑客)自学
    maven 本地jar打包到镜像仓库
    技术与产品:工业革命与时代进步的缩影
    基于AVDTP信令分析蓝牙音频启动流程
  • 原文地址:https://blog.csdn.net/loyd3/article/details/127765954