Vue中的函数式组件

423 阅读2分钟

最近在Vue2的深度学习中,接触到一个新概念——函数式组件。话说自己做Vue项目也一年有余了,居然都没用过这个叫做函数式组件的东西,实在有点...所以,决定好好学习了解一下。

一、 函数式组件的定义及写法

函数式组件是一个没有实例,即没有data、computed、watch,没有this上下文,没有生命周期,不监听任何属性,不管理任何状态,只有props传参的组件。

它的写法和我们常用的组件大致相同,但需需要添加 functional为ture 的声明。

【基本写法】

Vue.component('function-child', {
    functional: true,
    props: {
      opts: {
        type:Array,
        default: () => {
           return []
        },
      itemClick: {
        type: function,
        default: null 
      }  
    },
    render: function (createElement, context) {
      
    }
})

与非函数式组件相比,代码中多了两点:

  • 添加了一个functional: true的属性

  • render函数的参数多了一个context,用来作为上下文,弥补缺少的实例,也就是说,组件需要的一切都是通过 context 参数传递,它是一个包括如下字段的对象:

    • props:提供所有 prop 的对象
    • children:VNode 子节点的数组
    • slots:一个函数,返回了包含所有插槽的对象
    • scopedSlots:(2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。
    • data:传递给组件的整个数据对象
    • parent:对父组件的引用
    • listeners:(2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。
    • injections:(2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的 property。

【单文件组件】写法

<template functional>
    <div>
        <div v-for="item in props.opts" :key="item.value" @click="props.itemClick(item)">
            <span>{{item.label}}:</span>
            <span>{{item.value}}</span>
        </div>
    </div>
</template>

采用单文件写法时,需要注意以下变动:

  • 在template标签上追加一个funcitonal属性
  • 通过 props属性,父组件传入的props可以被访问到。
  • 因为函数式组件没有this,我们无法访问$emit方法,所以可以使用props中的一个函数进行触发事件。
  • 单文件组件中的script部分就不需要了。

二、函数式组件的引用

<template>
    <div>
        <function-child 
          :opts="opts" :itemClick="item => (activeItem = item)" 
        >
        </function-child>
    </div>
</template>
import FunctionChild from '@/components/FunctionChild.vue'
export default {
    components: {
        FunctionChild
    },
    data() {
        return {
            opts: [{
                label: 'label',
                value: '0'
            }],
            activeItem: ''
        }
    }
}

三、函数式组件的优点

函数式组件大抵可以被视作一个只接收一些prop并按预期返回某种渲染结果的fc(props) => VNode 函数,但其优点仍然很明显:

  • 因为函数式组件忽略了生命周期、监听等实现逻辑,所以渲染开销很低、执行速度快。
  • 函数式组件结构比较简单,代码结构更清晰

所以,当我们不需要复杂的组件,不需要在生命钩子函数里面做处理,仅仅只需要将外部传入的数据进行展现,比如一些不需要太多逻辑的UI组件、详情页面,就可以考虑用函数式组件。