10-异步组件与函数式组件

58 阅读2分钟

异步组件:指的是异步渲染组件

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()和生命周期钩子函数。