Vue.js如何在组件内复用模板而无需导出为新组件?
当然有啦!Vue 提供了几种不用单独导出组件就能复用模板片段的方案,完美匹配你的需求~下面针对不同Vue版本给你具体的实现方式:
Vue 2 实现方式(类似React渲染函数)
你可以在组件的methods里定义一个返回VNode的渲染函数,就像React里的函数式渲染片段一样:
<template> <div> <!-- 直接调用渲染函数生成内容 --> {{ renderIncrease(yearly) }} <YearlyChart/> {{ renderIncrease(monthly) }} <MonthlyTable/> {{ renderIncrease(weekly) }} </div> </template> <script> export default { data() { return { yearly: { text: "Yearly Sales", increase: 5 }, monthly: { text: "Monthly Sales Dropping", increase: -7.2 }, weekly: { text: "Awesome Weekly Sales!", increase: 0.2 } } }, methods: { spanClassName(increase) { return increase >= 0 ? 'text-success' : 'text-danger' }, iconClassName(increase) { return increase >= 0 ? 'fa fa-arrow-up' : 'fa fa-arrow-down' }, // 自定义渲染函数,返回VNode数组 renderIncrease(stat) { return [ this.$createElement('span', stat.text), this.$createElement('span', { class: this.spanClassName(stat.increase) }, [ this.$createElement('i', { class: this.iconClassName(stat.increase) }), `${stat.increase}%` ]) ] } } } </script>
Vue 3 实现方式(更简洁灵活)
在Vue 3中,你可以直接用h函数(Vue的虚拟DOM创建函数)结合<script setup>来实现,写法更接近React的风格:
<template> <div> <!-- 通过<component>渲染生成的VNode --> <component :is="renderIncrease(yearly)" /> <YearlyChart/> <component :is="renderIncrease(monthly)" /> <MonthlyTable/> <component :is="renderIncrease(weekly)" /> </div> </template> <script setup> import { h } from 'vue' import YearlyChart from './YearlyChart.vue' import MonthlyTable from './MonthlyTable.vue' // 定义数据 const yearly = { text: "Yearly Sales", increase: 5 } const monthly = { text: "Monthly Sales Dropping", increase: -7.2 } const weekly = { text: "Awesome Weekly Sales!", increase: 0.2 } // 工具函数 const spanClassName = (increase) => increase >= 0 ? 'text-success' : 'text-danger' const iconClassName = (increase) => increase >= 0 ? 'fa fa-arrow-up' : 'fa fa-arrow-down' // 渲染函数:返回单个根节点的VNode(Vue 3要求组件必须有单根) const renderIncrease = (stat) => { return h('div', [ h('span', stat.text), h('span', { class: spanClassName(stat.increase) }, [ h('i', { class: iconClassName(stat.increase) }), `${stat.increase}%` ]) ]) } </script>
备选方案:局部小型组件(开销极低)
如果你觉得渲染函数写起来有点繁琐,也可以在当前组件内部注册一个极小的局部组件,完全不需要单独导出文件,开销其实非常小:
<template> <div> <increase-display :stat="yearly" /> <YearlyChart/> <increase-display :stat="monthly" /> <MonthlyTable/> <increase-display :stat="weekly" /> </div> </template> <script setup> import YearlyChart from './YearlyChart.vue' import MonthlyTable from './MonthlyTable.vue' const yearly = { text: "Yearly Sales", increase: 5 } const monthly = { text: "Monthly Sales Dropping", increase: -7.2 } const weekly = { text: "Awesome Weekly Sales!", increase: 0.2 } // 局部注册小型组件 const IncreaseDisplay = { props: ['stat'], template: ` <span>{{ stat.text }}</span> <span :class="spanClassName(stat.increase)"> <i :class="iconClassName(stat.increase)"></i> {{ stat.increase }}% </span> `, methods: { spanClassName(increase) { return increase >= 0 ? 'text-success' : 'text-danger' }, iconClassName(increase) { return increase >= 0 ? 'fa fa-arrow-up' : 'fa fa-arrow-down' } } } </script>
这种方式的可读性其实比渲染函数更好,而且Vue对小型组件的优化已经做得非常到位,完全不用担心性能问题~
内容的提问来源于stack exchange,提问作者glinda93
相关产品推荐
相关产品推荐

