如何在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
相关产品推荐
相关产品推荐

