# 介绍

函数式组件是可以在没有状态管理的情况下,实现组件逻辑的函数。在组件中将其标记为functional

# 模版定义

<template functional>
  <div>{{ props.msg }}</div>
</template>

<script>
export default {
  props: {
    msg: {
      type: String,
      default: 'Hello World',
    },
  },
};
</script>

# render函数定义

export default {
  name: 'FunctionalComponent',
  functional: true,
  props: {
    msg: {
      type: String,
      default: 'Hello World',
    }
  },
  render(h, context) {
    return h('div', {}, [h('h2'), {}, context.props.msg])
  }
}
// render函数 context 参数介绍

组件需要的一切都是通过 context 参数传递,它是一个包括如下字段的对象:

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

# 定义一个函数式组件Button

# render函数方式

export default {
  name: 'MyButton',
  functional: true,
  props: {
    person: {
      type: Object,
      default: () => ({ name: '张小小', age: 23 }),
    },
  },
  render(h, { props, scopedSlots, listeners }) {
    // NOTE default 是关键字,需要重命名
    const { left, right, default: _defaultSlot } = scopedSlots
    const defaultSlot = (_defaultSlot && _defaultSlot({ person: props.person })) || <span>按钮</span>
    const leftSlot = (left && left()) || ''
    const rightSlot = right && right(props.person)
    const button = h(
      'button',
      {
        on: {
          click: () => {
            listeners.click && listeners.click(props.person)
          },
        },
      },
      [defaultSlot]
    )
    return (
      <div>
        {leftSlot}
        {button}
        {rightSlot}
      </div>
    )
  },
}

# 模版定义方式

<template functional>
  <div>
    <slot name="left"></slot>
    <button @click="listeners['click'] && listeners['click'](props.person)">
      <slot :person="props.person">
        <span>按钮</span>
      </slot>
    </button>
    <slot name="right" :age="props.age"></slot>
  </div>
</template>

<script>
  export default {
    name: 'MyButton',
    props: {
      person: {
        type: Object,
        default: () => ({ name: '张小小', age: 24 }),
      },
    },
  }
</script>

# 注意事项

  • 函数式组件不能使用this
  • 函数式组件不能使用data
  • 函数式组件不能使用watch
  • 函数式组件不能使用computed
  • 函数式组件不能使用methods
  • 函数式组件不能使用生命周期钩子