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

Vue3中仅父容器变化时,如何避免条件渲染的DOM重复?

Vue3中动态切换外层容器(避免重复子组件代码)

在Vue3组合式API场景下,当你需要通过布尔值控制是否用<TransitionGroup>(或其他容器组件)包裹子组件,同时不想重复编写子组件的大量属性时,可以用以下几种方案解决:

方案1:使用动态组件<component>

通过计算属性返回要渲染的容器组件,子组件只写一次:

<template>
  <div class="my-component">
    <component :is="containerComponent">
      <MyCoolComponent
        :it="prop1"
        :has="prop2"
        :lots="prop3"
        :of="prop4"
        :properties="prop5"
      />
    </component>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import MyCoolComponent from './MyCoolComponent.vue'

const props = defineProps({
  useTransitionGroup: Boolean,
  prop1: /* 类型定义 */,
  prop2: /* 类型定义 */,
  prop3: /* 类型定义 */,
  prop4: /* 类型定义 */,
  prop5: /* 类型定义 */
})

const containerComponent = computed(() => {
  return props.useTransitionGroup ? 'TransitionGroup' : 'div'
})
</script>

如果需要给容器组件加属性(比如TransitionGroup的tag或name),可以搭配v-bind动态绑定:

<template>
  <div class="my-component">
    <component 
      :is="containerComponent"
      v-bind="containerProps"
    >
      <MyCoolComponent
        :it="prop1"
        :has="prop2"
        :lots="prop3"
        :of="prop4"
        :properties="prop5"
      />
    </component>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import MyCoolComponent from './MyCoolComponent.vue'

const props = defineProps({
  useTransitionGroup: Boolean,
  prop1: /* 类型定义 */,
  prop2: /* 类型定义 */,
  prop3: /* 类型定义 */,
  prop4: /* 类型定义 */,
  prop5: /* 类型定义 */
})

const containerComponent = computed(() => {
  return props.useTransitionGroup ? 'TransitionGroup' : 'div'
})

const containerProps = computed(() => {
  if (props.useTransitionGroup) {
    return {
      tag: 'ul',
      name: 'list-transition'
    }
  }
  return {
    class: 'normal-container'
  }
})
</script>

方案2:用插槽抽离重复内容

可以在当前组件内用<template v-slot>复用子组件内容,减少重复代码:

<template>
  <div class="my-component">
    <template #content>
      <MyCoolComponent
        :it="prop1"
        :has="prop2"
        :lots="prop3"
        :of="prop4"
        :properties="prop5"
      />
    </template>

    <TransitionGroup v-if="useTransitionGroup" tag="ul" name="list-transition">
      <slot name="content" />
    </TransitionGroup>
    <div v-else class="normal-container">
      <slot name="content" />
    </div>
  </div>
</template>

<script setup>
import MyCoolComponent from './MyCoolComponent.vue'

defineProps({
  useTransitionGroup: Boolean,
  prop1: /* 类型定义 */,
  prop2: /* 类型定义 */,
  prop3: /* 类型定义 */,
  prop4: /* 类型定义 */,
  prop5: /* 类型定义 */
})
</script>

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

如果需要更灵活的逻辑控制,可以在setup中直接返回渲染函数:

import { h } from 'vue'
import MyCoolComponent from './MyCoolComponent.vue'

export default {
  props: {
    useTransitionGroup: Boolean,
    prop1: /* 类型定义 */,
    prop2: /* 类型定义 */,
    prop3: /* 类型定义 */,
    prop4: /* 类型定义 */,
    prop5: /* 类型定义 */
  },
  setup(props) {
    const child = h(MyCoolComponent, {
      it: props.prop1,
      has: props.prop2,
      lots: props.prop3,
      of: props.prop4,
      properties: props.prop5
    })

    return () => {
      if (props.useTransitionGroup) {
        return h('TransitionGroup', { tag: 'ul', name: 'list-transition' }, () => child)
      } else {
        return h('div', { class: 'normal-container' }, () => child)
      }
    }
  }
}

以上三种方案都能避免重复编写子组件代码,根据你的实际场景选择即可——动态组件方案最简洁,插槽方案可读性高,渲染函数适合复杂逻辑场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 22:32:45