You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vue单文件组件(SFC)中编写Render函数?TSX转SFC方法

基于路由meta.icon生成菜单的SFC实现及Render函数写法

一、TSX菜单组件转SFC实现

假设你的路由配置中meta.icon已传入AddSvgIcon.vue组件(支持直接引入或异步导入),以下是两种常用的SFC写法:

1. 模板式SFC(最常用)

<template>
  <ul class="menu-list">
    <li v-for="route in routes" :key="route.path" class="menu-item">
      <!-- 动态渲染传入的icon组件 -->
      <component :is="route.meta.icon" v-if="route.meta.icon" />
      <router-link :to="route.path">{{ route.meta.title }}</router-link>
    </li>
  </ul>
</template>

<script setup>
const props = defineProps({
  routes: {
    type: Array,
    required: true
  }
})
</script>

<style scoped>
.menu-list {
  list-style: none;
  padding: 0;
}
.menu-item {
  margin: 8px 0;
  padding: 8px;
  display: flex;
  align-items: center;
  gap: 8px;
}
</style>

2. 选项式API写法(兼容传统习惯)

<template>
  <ul class="menu-list">
    <li v-for="route in routes" :key="route.path" class="menu-item">
      <component :is="route.meta.icon" v-if="route.meta.icon" />
      <router-link :to="route.path">{{ route.meta.title }}</router-link>
    </li>
  </ul>
</template>

<script>
import { defineComponent } from 'vue'

export default defineComponent({
  props: {
    routes: {
      type: Array,
      required: true
    }
  }
})
</script>

<style scoped>
/* 样式同上 */
.menu-list {
  list-style: none;
  padding: 0;
}
.menu-item {
  margin: 8px 0;
  padding: 8px;
  display: flex;
  align-items: center;
  gap: 8px;
}
</style>

二、SFC中编写Render函数的两种方式

1. 选项式API中使用render选项

直接通过h函数(createElement的别名)构建虚拟DOM:

<script>
import { defineComponent, h } from 'vue'
import { RouterLink } from 'vue-router'

export default defineComponent({
  props: {
    routes: {
      type: Array,
      required: true
    }
  },
  render() {
    return h('ul', { class: 'menu-list' }, this.routes.map(route => {
      // 生成icon节点
      const iconNode = route.meta.icon ? h(route.meta.icon) : null
      // 生成菜单项节点
      return h('li', { key: route.path, class: 'menu-item' }, [
        iconNode,
        h(RouterLink, { to: route.path }, route.meta.title)
      ])
    }))
  }
})
</script>

<style scoped>
/* 样式同上 */
.menu-list {
  list-style: none;
  padding: 0;
}
.menu-item {
  margin: 8px 0;
  padding: 8px;
  display: flex;
  align-items: center;
  gap: 8px;
}
</style>

2. <script setup>中结合useRender(Vue 3.3+)

通过useRender注册渲染函数,更贴合组合式API风格:

<script setup>
import { h, useRender } from 'vue'
import { RouterLink } from 'vue-router'

const props = defineProps({
  routes: {
    type: Array,
    required: true
  }
})

useRender(() => {
  return h('ul', { class: 'menu-list' }, props.routes.map(route => {
    const iconNode = route.meta.icon ? h(route.meta.icon) : null
    return h('li', { key: route.path, class: 'menu-item' }, [
      iconNode,
      h(RouterLink, { to: route.path }, route.meta.title)
    ])
  }))
})
</script>

<style scoped>
/* 样式同上 */
.menu-list {
  list-style: none;
  padding: 0;
}
.menu-item {
  margin: 8px 0;
  padding: 8px;
  display: flex;
  align-items: center;
  gap: 8px;
}
</style>

注意事项

  • 如果路由meta.icon是异步组件(如() => import('./AddSvgIcon.vue')),Vue会自动处理加载逻辑,无需额外配置。
  • <component :is="...">是SFC模板中渲染动态组件的标准方案,支持传入组件对象、异步组件或组件名称。
  • h函数的参数结构:h(标签/组件, props属性对象, 子节点数组/文本内容)。

内容的提问来源于stack exchange,提问作者jaycethanks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 18:46:28