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

Vue3组件多布局变体的无冗余代码实现方案咨询

Vue3 布局变体优化方案

针对你遇到的两种布局变体代码冗余问题,以下是几种简洁的实现方式:

方案1:模板内仅判断差异部分

只在布局的差异节点做条件判断,公共结构复用,避免全量代码重复:

<script setup>
const props = defineProps({
  layout: {
    type: String,
    default: 'top-row',
    validator: val => ['top-row', 'left-col'].includes(val)
  }
})
</script>

<template>
  <div class="flex flex-col">
    <div class="flex">
      <InnerComponent1 />
      <!-- 第一处差异:顶部布局显示InnerComponent2,左侧布局显示插槽 -->
      <InnerComponent2 v-if="layout === 'top-row'" />
      <slot v-else />
    </div>
    <!-- 第二处差异:顶部布局显示插槽,左侧布局显示InnerComponent2 -->
    <slot v-if="layout === 'top-row'" />
    <InnerComponent2 v-else />
  </div>
</template>

方案2:使用渲染函数(h函数)

通过JS逻辑生成VNode,把布局结构封装成函数,适合需要动态调整结构的场景:

<script setup>
import { h } from 'vue'
import InnerComponent1 from './InnerComponent1.vue'
import InnerComponent2 from './InnerComponent2.vue'

const props = defineProps({
  layout: {
    type: String,
    default: 'top-row',
    validator: val => ['top-row', 'left-col'].includes(val)
  }
})

const renderLayout = () => {
  const innerContent = props.layout === 'top-row'
    ? [h(InnerComponent1), h(InnerComponent2)]
    : [h(InnerComponent1), h('slot')]

  const bottomContent = props.layout === 'top-row'
    ? h('slot')
    : h(InnerComponent2)

  return h('div', { class: 'flex flex-col' }, [
    h('div', { class: 'flex' }, innerContent),
    bottomContent
  ])
}
</script>

<template>
  <render-layout />
</template>

方案3:拆分为布局子组件

把两种布局封装成独立子组件,主组件根据props动态渲染,适合布局后续可能扩展的场景:

先创建两个布局子组件

  • LayoutTopRow.vue:
<template>
  <div class="flex flex-col">
    <div class="flex">
      <InnerComponent1 />
      <InnerComponent2 />
    </div>
    <slot />
  </div>
</template>
  • LayoutLeftCol.vue:
<template>
  <div class="flex flex-col">
    <div class="flex">
      <InnerComponent1 />
      <slot />
    </div>
    <InnerComponent2 />
  </div>
</template>

主组件动态渲染

<script setup>
import { defineAsyncComponent } from 'vue'

const props = defineProps({
  layout: {
    type: String,
    default: 'top-row',
    validator: val => ['top-row', 'left-col'].includes(val)
  }
})

// 按需加载对应布局组件
const LayoutComponent = defineAsyncComponent(() => {
  return props.layout === 'top-row'
    ? import('./LayoutTopRow.vue')
    : import('./LayoutLeftCol.vue')
})
</script>

<template>
  <LayoutComponent>
    <slot />
  </LayoutComponent>
</template>

选择建议

  • 布局差异极小:选方案1,代码最直观,学习成本低
  • 需要动态生成复杂结构:选方案2,灵活性更高
  • 布局后续可能迭代扩展:选方案3,模块化更强,便于维护

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 19:50:09