代码运行结果
代码示例
let asyncComponent = defineAsyncComponent({
loader: async () => {
await new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 3000)
})
return import('./test.js').then(data => data.default)
},
timeout: 2000,
delay: 1000,
loadingComponent: {
render: () => {
return h('div', 'loading…………')
}
},
errorComponent: {
render: () => {
return h('div', 'error…………')
}
}
})
createApp(asyncComponent).mount('#app')
// ./test.js
const App = {
setup() {
return () => h('div', 'App')
}
}
export default App
第一:首先调用 defineAsyncComponent 函数,并传入 option. 在 函数中初始化状态后,返回一个 defineComponent 定义的组件对象。
const {
loader,
loadingComponent,
errorComponent,
delay = 200,
timeout, // undefined = never times out
suspensible = true,
onError: userOnError
} = source
let retries = 0
const retry = () => {
retries++
pendingRequest = null
return load()
}
const load = (): Promise<ConcreteComponent> => {}
return defineComponent({
return () => {
if (loaded.value && resolvedComp) {
return createInnerComp(resolvedComp, instance)
} else if (error.value && errorComponent) {
return createVNode(errorComponent as ConcreteComponent, {
error: error.value
})
} else if (loadingComponent && !delayed.value) {
return createVNode(loadingComponent as ConcreteComponent)
}
}
}
}) as T
第二:执行,createApp(asyncComponent).mount('#app'),执行 asyncComponent 组件对象的 setup 函数:
- 初始化 loaded, error, delay 响应式状态。
- 调用 load 函数,调用我们传入的 loader 异步函数。异步函数中异步 resolve 挂起微任务队列。继续执行同步任务。
- 同步任务继续执行,判断当前 loaded 状态为 false, 然后 delay 为 true, 白屏渲染。
return () => {
if (loaded.value && resolvedComp) {
return createInnerComp(resolvedComp, instance)
} else if (error.value && errorComponent) {
return createVNode(errorComponent as ConcreteComponent, {
error: error.value
})
} else if (loadingComponent && !delayed.value) {
return createVNode(loadingComponent as ConcreteComponent)
}
}
- delay 一秒之后,将 delay 置为 false, delay 响应式对象触发组件更新,重新执行 render 函数,然后 delay 为 false 和 loadingComponent, loadingComponent渲染。
if (delay) {
setTimeout(() => {
delayed.value = false
}, delay)
}
-
timout 到第三秒的时候,这时 loaded 仍然为 false,但是触发超时,error 响应式对象触发组件更新,触发 onError 函数,errorComponent渲染
-
等到第三秒的时候,resolve 的微任务队列执行。拿到要渲染的组件对象赋值给 resolvedComp,然后将 loaded 置为 true, loaded 响应式对象触发组件更新, 显示 App 组件。
return () => {
if (loaded.value && resolvedComp) {
return createInnerComp(resolvedComp, instance)
} else if (error.value && errorComponent) {
return createVNode(errorComponent as ConcreteComponent, {
error: error.value
})
} else if (loadingComponent && !delayed.value) {
return createVNode(loadingComponent as ConcreteComponent)
}
}
至此异步组件渲染完毕。