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

