前言

本笔记主要基于官方文档《迁移策略—— 函数式组件》汇总而来。如有理解出入,请以官方文档为主。建议您以官方文档为主,本文为辅。这样您可以“以自己为主”审视的阅读,从而不被我的观点带偏。

知识储备

概述

  • Vue 3.x 对有状态组件的性能进行了提升,与函数式组件的性能相差无几。所以,建议只使用有状态组件。

函数式组件的介绍

​ 函数式组件是一种比较简单,没有管理任何状态,也没有监听任何传递给它的状态,也没有生命周期方法的组件(与之相反的是有 stateful components状态组件)。实际上,它只是一个接受一些 prop 的函数。在这样的场景下,我们可以将组件标记为 functional,这意味它无状态 (没有响应式数据),也没有实例 (没有 this 上下文)。一个函数式组件就像这样:

Vue.component('my-component', {
  functional: true,
  // Props 是可选的
  props: {
    // ...
  },
  // 为了弥补缺少的实例
  // 提供第二个参数作为上下文
  render: function (createElement, context) {
    // ...
  }
})

函数式组件更详细的说明请查询:函数式组件

在 Vue 2.x 中,函数式组件主要有两个特点:

  • 因为函数式组件只是函数,所以渲染开销也低很多,初始化比有状态的组件快很多。
  • 可以返回多个根节点

然而,在 Vue 3.x 中,有状态组件的性能已经得到提升,与函数式组件的相差无几了。此外,现在有状态组件同样可以返回多个根节点的。因此,函数式组件仅剩的特点就只有比较简单。例如,用于创建动态标题组件。所以,Vue3.x 建议更多的去使用有状态组件。

Vue 2.x 函数式组件的用法

以创建动态标题组件为例:

函数写法
export default {
  functional: true,
  props: ['level'],
  render(h, { props, data, children }) {
    return h(`h${props.level}`, data, children)
  }
}
单文件组件写法
<template functional>
  <component
    :is="`h${props.level}`"
    v-bind="attrs"
    v-on="listeners"
  />
</template>

<script>
export default {
  props: ['level']
}
</script>

Vue 3.x 函数式组件的用法

函数写法

相较于 Vue 2.x 有三点变化:

  • 在 Vue 3.x 中,所有的函数式组件都是由普通函数创建的。以此,不需要添加functional: true
  • export default导出的是一个函数,函数有两个参数:
    • props
    • context(上下文):context是一个对象,包含attrsslotemit属性
  • h函数需要全局导入
import { h } from 'vue'

const DynamicHeading = (props, context) => {
  return h(`h${props.level}`, context.attrs, context.slots)
}

DynamicHeading.props = ['level']

export default DynamicHeading
单文件组件写法

相较于 Vue 2.x 有两点变化:

  • 移除functional
  • 重命名propsattrs$props$attrs
<template>
  <component
    v-bind:is="`h${$props.level}`"
    v-bind="$attrs"
  />
</template>

<script>
export default {
  props: ['level']
}
</script>
主要区别:
  • functional属性从template中移除

  • listeners移到$attrs


本系列目录

Logo

前往低代码交流专区

更多推荐