Skip to content

SFC 局部 JSX/TSX

局部使用 JSX 不要求整个 SFC 都改成 render。外层可以继续使用 template,只在 script 中声明并注册局部 JSX 子组件。

template + 局部 JSX

vue
<template>
  <article class="demo-card">
    <span class="case-label">局部 JSX + template</span>
    <h3>LocalJsxInSfc.vue</h3>
    <LocalBadge :text="message" />
    <p>外层仍使用 template,局部子组件在 script lang="jsx" 中使用 JSX。</p>
    <button class="button" @click="count += 1">更新局部 JSX:{{ count }}</button>
  </article>
</template>

<script lang="jsx">
const LocalBadge = {
  name: 'LocalJsxBadge',
  functional: true,
  props: { text: String },
  render(h, { props }) {
    return <span class="badge">{props.text}</span>
  }
}

export default {
  name: 'LocalJsxInSfc',
  components: { LocalBadge },
  data() {
    return { count: 0 }
  },
  computed: {
    message() {
      return `局部 JSX 计数:${this.count}`
    }
  }
}
</script>

template + 局部 TSX

vue
<template>
  <article class="demo-card">
    <span class="case-label">局部 TSX + template</span>
    <h3>LocalTsxInSfc.vue</h3>
    <LocalMetric :label="label" :value="value" />
    <p>局部函数式子组件带 TypeScript 类型,外层仍是普通 Vue 模板。</p>
    <button class="button" @click="value += 1">value + 1</button>
  </article>
</template>

<script lang="tsx">
type MetricContext = {
  props: { label: string; value: number }
}

const LocalMetric = ({ props }: MetricContext) => (
  <span class="metric">
    <small>{props.label}</small>
    <strong>{props.value}</strong>
  </span>
)

export default {
  name: 'LocalTsxInSfc',
  components: { LocalMetric },
  data(): { label: string; value: number } {
    return { label: '局部 TSX', value: 7 }
  }
}
</script>

这种模式适合表格单元格、局部图标、动态内容渲染器等需要 JSX 表达力,但仍希望保留 template 可读性的组件。

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