如何在Vue/Nuxt中动态渲染组件,复刻Next.js的BlockManager逻辑?
Nuxt.js 动态区块渲染完整实现方案
1. 前置路由配置(对应Next.js的catch-all路由)
- Nuxt2 路由规则:在
pages/目录下创建_.vue文件捕获所有slug - Nuxt3 路由规则:在
pages/目录下创建[...slug].vue文件捕获所有slug - 页面中通过
useRoute()(Nuxt3)或$route(Nuxt2)获取slug参数,请求API拿到页面blocks数据,传入BlockManager组件即可。
2. BlockManager 核心实现(Vue/Nuxt对应React动态渲染逻辑)
Vue 提供原生的动态组件语法<component :is="xxx",完全可以对标你React里的动态组件渲染逻辑,以下是完整的单文件组件实现:
Nuxt3 版本示例
<!-- components/BlockManager.vue --> <template> <div> <component v-for="(block, index) in blocks" :key="`index-${index}`" :is="getBlockComponent(block.__component)" v-bind="getBlockProps(block)" /> </div> </template> <script setup> // 手动导入区块组件(如果不用Nuxt自动导入的话) import Hero from '~/components/blocks/Hero.vue' import Pricing from '~/components/blocks/Pricing.vue' // 组件映射表,替代原来的switch逻辑,更易维护 const componentMap = { 'blocks.hero': Hero, 'blocks.prices': Pricing } // 入参声明 const props = defineProps({ blocks: { type: Array, default: () => [] } }) // 获取对应组件 const getBlockComponent = (componentName) => { return componentMap[componentName] || null } // 剥离__component属性,返回组件需要的props const getBlockProps = (block) => { const { __component, ...rest } = block return rest } </script>
自动注册简化方案(无需手动导入组件)
Nuxt 默认开启组件自动导入功能,你只需要把所有区块组件放在components/blocks/目录下,命名和__component字段对应即可,比如blocks.hero对应components/blocks/Hero.vue,上述代码可以进一步简化,不需要手动import和维护映射表:
<script setup> const props = defineProps({ blocks: { type: Array, default: () => [] } }) // 直接把__component字段转换为Nuxt自动注册的组件名即可,命名转换规则可根据自己的实际命名调整 const getBlockComponent = (componentName) => { // 示例规则:把blocks.hero转为BlocksHero,匹配自动导入的组件名 return componentName.split('.').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join('') } const getBlockProps = (block) => { const { __component, ...rest } = block return rest } </script>
3. 核心逻辑对应说明
你原代码里的return Block ? <Block key={index-${index}} {...rest}/> : null;,在Vue里的等价逻辑完全对齐:
:is="getBlockComponent(block.__component)对应获取要渲染的组件,无匹配组件返回null时不会渲染任何内容v-bind="getBlockProps(block)"对应{...rest}透传所有组件所需属性:key="index-${index}`` 和React的key作用完全一致,用于列表渲染的Diff优化
内容的提问来源于stack exchange,提问作者Haukez
相关产品推荐
相关产品推荐

