Vue的函数式组件是什么?

# Vue的函数式组件是什么?


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

  • 无状态:函数式组件本身式没有状态的,也就是没有响应式数据
  • 无实例:函数式组件没有实例,也就是没有this上下文
export default {
  fuctionl: true,
  // Props 是可选的
  props: {
    // ...
  },
  // 为了弥补缺少的实例
  // 提供第二个参数作为上下文
  render: function (createElement, context){
    // ...
  }
}

# 参数:

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

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

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

# render函数


1. render函数是函数式组件
2. render函数有两个参数,一个是createElement,一个是Context: 
- createElemet 是创建虚拟dom的函数
- context 是函数式组件的上下文,它包括:
- - props: 提供所有 prop 的对象
- - children: VNode 子节点的数组
- - slots: 一个函数,返回了包含所有插槽的对象
- - scopedSlots: 一个暴露传入的作用域插槽的对象,也以函数形式暴露普通插槽
- - data: 传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件
- - parent: 对父组件的引用
- - listeners: 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名
- - injections: 如果使用了 inject 选项,则该对象包含了应当被注入的属性
由于函数式组件没有创建组件实例,所有传统的通过this来调用的属性,在这里都需要通过context来调用
Vue.compoent('my-fuctional-button', {
  functional: true,
  render: fuction (createElement, context) {
    return createElement('button', context.data, context.children)
  }
})
// context 中的 slots() 和 children
// slots 返回的是map化的非作用域插槽,key是slot的名字,value是slot的内容,所有我们可以通过slots().default来调用指定的插槽。
// children 是一个数组,包含了所有的非作用域插槽。所以我们可以很简单的把在所有插槽传递给下一个函数进行处理
<func-comp>
  <div slot-scopte="scope">{{ 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

createElement是创建虚拟Dom的函数。此处引入createElement参数:

// @return {VNode}
createElement(
// {String | Object | Function}
// 一个 HTML 标签名、组件选项对象,或者 resolve 了上述任何一种的一个 async 函数。必填项

'div',

// {Object}
// 一个与模板中 attribute 对应的数据对象,可选。
{
  // ...
},

// {String | Array}
// 子级虚拟节点(VNode),由'createElement()'构建而成,也可以使用字符串来生成'文本虚拟节点',可选。
[
  '先写一些文字',
  createElement('h1', '一则头条'),
  createElement(MyCompoent, {
    props: {
      someProp: 'foobar'
    }
  })
]

)