Skip to content

函数式组件

显式 functional SFC

vue
<script lang="jsx">
export default {
  name: 'FunctionalSfcJsx',
  functional: true,
  props: { text: String },
  render(h, context) {
    return (
      <article {...context.data} class={['demo-card', context.data.class]}>
        <span class="case-label">functional SFC / JSX</span>
        <h3>{context.props.text}</h3>
        <p>显式 functional: true,使用 context.props、context.data 与 children。</p>
        {context.children}
      </article>
    )
  }
}
</script>
vue
<script lang="tsx">
type FunctionalContext = {
  props: { text: string; count: number }
  data: Record<string, unknown>
}

export default {
  name: 'FunctionalSfcTsx',
  functional: true,
  props: {
    text: { type: String, default: '' },
    count: { type: Number, default: 0 }
  },
  render(h: any, context: FunctionalContext) {
    return (
      <article class="demo-card">
        <span class="case-label">functional SFC / TSX</span>
        <h3>{context.props.text}</h3>
        <p>带类型的 functional render,当前外部计数:{context.props.count}</p>
      </article>
    )
  }
}
</script>

箭头函数语法糖

大写变量名、箭头函数、直接返回 JSX 的声明会转换为 { functional: true, render }

jsx
export const FunctionalArrowJsx = ({ props, listeners }) => (
  <article class="demo-card compact-card">
    <span class="case-label">functional sugar / JSX</span>
    <h3>{props.label}</h3>
    <button class="button" onClick={listeners.activate}>触发父组件事件</button>
  </article>
)
tsx
type ArrowContext = {
  props: { label: string; value: number }
}

export const FunctionalArrowTsx = ({ props }: ArrowContext) => (
  <article class="demo-card compact-card">
    <span class="case-label">functional sugar / TSX</span>
    <h3>{props.label}</h3>
    <p>类型化 props value:{props.value}</p>
  </article>
)

普通 items.map(item => <li />) 不会被误判为 functional component。

基于 Oxc Parser 的 Vue 2.7 JSX/TSX 转换器