vue函数式组件

参照 https://blog.csdn.net/weixin_41275295/article/details/100189869

vue 提供了一种称为函数式组件的组件类型,用来定义那些没有响应数据,也不需要有任何生命周期的场景,它只接受一些props 来显示组件。

1.使用方法

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

或者单文件定义函数式组件(2.5版本后)

<template functional>
  <button
    class="btn btn-primary"
    v-bind="data.attrs"
    v-on="listeners"
  >
    <slot/>
  </button>
</template>

2.参数

1.functional
设置为true 即表示该组件为一个函数组件
2.props(可选)
传递值到组件内部,2.3.0版本后可以省略,框架会自动将组件上的特性解析为prop
3.render函数
提供渲染函数来返回一个vnode

3.和正常自定义组件的区别?

1.不维护响应数据
2.无钩子函数
3.没有instance实例
4.所以在组件内部没有办法像传统组件一样通过this来访问组件属性
5.正是因为函数式组件精简了很多例如响应式和钩子函数的处理,因此渲染性能会有一定的提高,所以如果你的业务组件是一个纯展示且不需要有响应式数据状态的处理的,那函数式组件会是一个非常好的选择。

4.render函数

1.render函数是函数式组件最重要的参数,且是必须的。
2.render函数有两个参数,一个是createElement,一个是context
createElement 是创建虚拟dom的函数
context 是函数式组件的上下文,它包括:
    props:提供所有 prop 的对象
    children: VNode 子节点的数组
    slots: 一个函数,返回了包含所有插槽的对象
    scopedSlots: (2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。
    data:传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件
    parent:对父组件的引用
    listeners: (2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。
    injections: (2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的属性。
由于函数式组件没有创建组件实例,所有传统的通过this来调用的属性,在这里都需要通过context来调用
Vue.component('my-functional-button', {
  functional: true,
  render: function (createElement, context) {
    return createElement('button', context.data, context.children)
  }
})

5.context中的 slots()和children

slots 返回的是map化的非作用域插槽,key是slot的名字,value是slot的内容,所有我们可以通过slots().default 来调用指定的插槽。
children 是一个数组,包含了所有的非作用域插槽。所以我们可以很简单的把所有插槽传递给下一个函数进行处理。

6.context中的scopedSlots使用演示

<func-comp>
   <div slot-scope="scope">demo functional component {{scope.a}}</div>
</func-comp>
Vue.component('func-comp', { functional: true, props: { name: String }, render (createElement, context) { return createElement('div', context.data, [context.scopedSlots.default({ a:1 })]) } })

显示结果:demo functional component 1
原文地址:https://www.cnblogs.com/qxp140605/p/13719582.html