异步组件:指的是异步渲染组件
1、异步组件要解决的问题
1.组件加载失败,是否渲染Error
2.组件加载时,是否显示占位内容
3.是否延迟展示loading
4.加载失败是否重试
2、异步组件的实现原理
异步组件本质上是通过封装来实现方便的用户接口
基本实现如下
function defineAsyncComponent(loader) {
//创建一个变量,存储异步加载组件
let InnerComp = null
// 返回一个包装组件
return {
nane: 'AsyncComponentWrapper',
setup() {
// 异步组件是否加载成功
const loaded = ref(false)
// 执行加载函数,返回一个Promise实例
// 加载成功后,赋值给InnerComp loaded标记为true,代表加载成功
loader().then(c => {
InnerComp = c
loaded.vale = true
})
return () => {
//如果异步组件加载成功,则渲染该组件,否则渲染一个占位内容
return loaded.vale ? {type: InnerComp} : {type:Text, children:''}
}
}
}
}
注意:
1.defineAsyncComponent函数本质上是一个高阶组件,返回值是一个包装组件
2.包装组件如果渲染失败则会渲染占位内容
3.占位内容通常是一个注释节点
3、函数式组件
函数式组件本质是一个函数,返回的是一个虚拟DOM,函数组件没有自身状态,但可以接收外部传入的props
实现如下
function MyFuncComp(props) {
return {type: 'h1', children: props.title}
}
// 定义props
MyFuncComp.props = {
title: String
}
挂载逻辑可以使用之前的mountComponent,主体部分不再赘述,对vnode.type进行判断,如果类型是对象,则是有状态组件,如果类型是函数,则是函数式组件
调整mountComponent部分逻辑,代码如下
function mountComponent(vnode, container, anchor) {
// 检查是否是函数式组件
const isFunctional = typeof vnode.type === 'function'
let componentOptions = vnode.type
if (isFunctional) {
// 如果是函数式组件,则将vnode.type作为渲染函数,将vnode.type.props作为props选项定义
componentOptions = {
render: vnode.type,
props: vnode.type.props
}
}
}
函数式组件性能略好,没有初始化data和生命周期钩子函数
总结
1、学习了异步组件要解决的问题,异步组件的实现,加载占位内容,加载错误是否重试。
2、函数式组件,本质上是一个函数,本身没有状态,但可以接收状态。没有data()和生命周期钩子函数。