Vue条件渲染如何避免重复子组件?附自定义按钮场景
避免Vue条件渲染中重复子组件的实用方案
针对你这个自定义按钮组件的场景,完全可以通过两种简单的方式消除重复代码,既让组件更简洁,也方便后续维护:
方案一:用动态组件 <component :is="..."> 实现标签切换
这是最优雅的解决方案,直接根据type动态切换外层的<a>或<button>,公共子内容只需要写一次:
<template> <component :is="type === 'link' ? 'a' : 'button'" v-bind="type === 'link' ? { href } : { type: type }" > <span class="btn-label"><slot></slot></span> </component> </template> <script> export default { props: { type: { type: String, default: 'button', // 添加入参校验,避免非法类型 validator: val => ['button', 'link', 'submit', 'reset'].includes(val) }, href: { type: String, default: '' } } } </script>
为什么这么做?
<component :is="...">是Vue专门用来动态渲染元素/组件的语法,完美适配这种“二选一”的标签切换场景v-bind的对象语法可以根据类型动态传递属性:给<a>传href,给<button>传原生的type属性- 公共的
<span class="btn-label"><slot></slot></span>只写一次,彻底告别重复代码
方案二:抽取公共模板片段(适合复杂公共内容)
如果你的按钮内部后续可能添加更多公共元素,也可以把重复部分抽成可复用的模板片段:
<template> <a v-if="type === 'link'" :href="href"> <btn-content /> </a> <button v-else :type="type"> <btn-content /> </button> <!-- 定义公共模板片段 --> <template #btn-content> <span class="btn-label"><slot></slot></span> <!-- 后续新增的公共元素都可以放在这里 --> </template> </template>
要是用的Vue 3,还可以直接定义一个极简的局部组件来复用:
<template> <a v-if="type === 'link'" :href="href"> <BtnContent /> </a> <button v-else :type="type"> <BtnContent /> </button> </template> <script setup> import { h, useSlots } from 'vue' // 局部组件,专门渲染按钮的公共内容 const BtnContent = () => h('span', { class: 'btn-label' }, () => [useSlots().default?.()]) </script>
方案怎么选?
如果只是切换原生HTML标签,方案一的动态组件绝对是最优解,代码最少、维护成本最低;如果公共内容会越来越复杂,或者需要在组件外复用,方案二的模板片段/局部组件会更灵活。
内容的提问来源于stack exchange,提问作者Jaye Renzo Montejo
相关产品推荐
相关产品推荐

