开发提速?Vue3模板隐藏技巧来了

🤔 为什么需要"模板函数"

在 Vue 2 Options API 时代,复用一段 纯 UI 片段 只有两条路:

  1. 💼 抽成组件 → 为了三五行模板写 .vue、props、emits,

  2. 📋 直接复制粘贴 → 维护地狱,一改全改。

Vue 3 带来了 组合式 API ,让逻辑可以"组合",但 <template> 依旧只能"整块"复用。

vue-reuse-template(已并入 VueUse)把"组合"思想延伸到模板层,让你:

  • 🎯 把模板当函数定义(define)

  • 🔁 在原地多次调用(reuse)

  • 🚫 不创建额外组件实例不破坏作用域不传 props


⚙️ 核心概念:一对"模板 Hook"

typescript 复制代码
const [DefineTemplate, ReuseTemplate] = createReusableTemplate()

| 名称 | 作用 | 是否渲染 |

| --- | --- | --- |

| DefineTemplate | 📝 声明模板片段 | ❌(占位) |

| ReuseTemplate | ▶️ 调用模板片段 | ✅(真正渲染) |


📦 安装与引入

bash 复制代码
# 推荐直接装 VueUse

npm i @vueuse/core
vue 复制代码
<script setup>

import { createReusableTemplate } from '@vueuse/core'

</script>

  

🚀 最小可运行示例

vue 复制代码
<script setup>

import { createReusableTemplate } from '@vueuse/core'

  


// 1. 创建一对模板 Hook

const [DefineCard, ReuseCard] = createReusableTemplate()

</script>

<template>

  <!-- 2. 定义:不会渲染,只是注册 -->

  <DefineCard v-slot="{ title, content }">

    <div class="card">

      <h3>{{ title }}</h3>

      <p>{{ content }}</p>

    </div>

  </DefineCard>

  <!-- 3. 复用:真正渲染 -->

  <ReuseCard title="文章 1" content="今天学了 vue-reuse-template" />

  <ReuseCard title="文章 2" content="模板也能当函数用" />

</template>

<style scoped>

.card { border: 1px solid #ccc; padding: 12px; margin: 8px 0; }

</style>

  

🎯** 效果**:两张卡片,零组件文件,零 props。


🔧 进阶技巧

解构命名 & 多次定义

typescript 复制代码
const { define: DefineChip, reuse: ReuseChip } = createReusableTemplate()

  


const [DefineBadge, ReuseBadge] = createReusableTemplate()

在循环里复用

vue 复制代码
<ReuseCard

  v-for="post in posts"

  :key="post.id"

  :title="post.title"

  :content="post.body"

/>

与组件作用域无缝衔接

模板内部可直接使用当前组件的变量、注入、Router、Store:

vue 复制代码
<script setup>

import { useUserStore } from '@/stores/user'

const userStore = useUserStore()

</script>

<DefineCard v-slot="{ title }">

  <h3>{{ title }}</h3>

  <p>当前用户:{{ userStore.name }}</p>

</DefineCard>

  

具名插槽 + 默认插槽

vue 复制代码
<DefineComplex v-slot="{ title }">

  <header>{{ title }}</header>

  <slot name="extra" />

</DefineComplex>

<ReuseComplex title="标题">

  <template #extra><button>更多</button></template>

</ReuseComplex>

  

🎯 TypeScript 泛型推导(可选)

typescript 复制代码
const [Define, Reuse] = createReusableTemplate<{

  title: string

  done: boolean

}>()

  


// 如果写 :title="123" 会立即报错

📊 与"全局注册"插件的区别

| 方案 | 跨组件 | 是否需插件 | 是否运行时 | 插槽传参 |

| --- | --- | --- | --- | --- |

| createReusableTemplate | ❌(仅当前组件) | 否 | 否 | ✅ |

| unplugin-vue-reuse-template | ✅ | 是(编译) | 否 | ✅(实验) |

💡 80% 场景 单组件内复用 已够用;如需 任意组件 调用,再考虑插件。


💡 示例:低代码表单渲染器

vue 复制代码
<script setup>

import { createReusableTemplate } from '@vueuse/core'

  


const [DefineField, ReuseField] = createReusableTemplate()

  


const schema = [

  { type: 'input', label: '姓名', key: 'name' },

  { type: 'select', label: '城市', key: 'city', options: ['北京', '上海'] }

]

  


const form = reactive({})

</script>

<template>

  <!-- 定义:一行通用字段 -->

  <DefineField v-slot="{ field }">

    <label>{{ field.label }}

      <input v-if="field.type==='input'" v-model="form[field.key]" />

      <select v-else v-model="form[field.key]">

        <option v-for="o in field.options" :key="o">{{ o }}</option>

      </select>

    </label>

  </DefineField>

  <!-- 渲染 -->

  <ReuseField v-for="f in schema" :key="f.key" :field="f" />

  


  <pre>{{ form }}</pre>

</template>

  

** 亮点**

  • 🚫 没有为"字段"创建额外组件

  • 🔗 仍能访问 form 响应式对象

  • 📖 模板即函数,可读性高


⚡ 性能与原理

  1. ⏱️ 编译期DefineTemplate 被编译成 渲染函数块并缓存

  2. ▶️ 运行时ReuseTemplate 直接 调用该函数块,不生成新的组件实例

  3. 🔗 作用链 :通过 Vue 3 的 作用域插槽 保持变量访问

  4. 🧹 零内存泄漏:随组件卸载自动回收


⚠️ 常见坑与最佳实践

| 问题 | 解决方案 |

| --- | --- |

| 🚨 模板未定义 | 保证 Define*Reuse* 之前渲染(同一组件内) |

| 🌐 跨组件复用 | 目前 做不到,请改用插件或抽正式组件 |

| 🪆 大量嵌套 | 模板函数也能"组合"------在 DefineA 内部再 ReuseB |

| 🏷️ 命名冲突 | 统一前缀:DefineUserCardDefineProductCard |

📋 何时用 & 何时不用

适合

  • 🎯 同组件内 重复 UI 结构(卡片、按钮组、表单项)

  • 🚫 逻辑简单,不值得为 props 写接口

  • 🔗 需要 访问父组件变量(不想层层传递)

不适合

  • 🌐 跨组件复用(目前做不到)

  • 🧠 业务逻辑复杂(应抽独立组件)

  • ⚡ 需要 keep-alive生命周期name 等组件特性


🎯 小结

vue-reuse-template模板也能像函数一样被定义和调用,不写 props、不创组件、不打断作用域------是 Vue 3 组合式时代里,最轻量的"模板函数"方案。


🚀 快速上手(单组件)

vue 复制代码
<script setup>

import { createReusableTemplate } from '@vueuse/core'

const [Def, Reuse] = createReusableTemplate()

</script>

<template>

  <Def v-slot="{ txt }"><p>{{ txt }}</p></Def>

  <Reuse txt="Hello" />

  <Reuse txt="World" />

</template>

  

🌍 全局注册(任意 .vue 可用)

① 安装插件

bash 复制代码
npm i -D unplugin-vue-reuse-template

② Vite 配置

typescript 复制代码
// vite.config.js

import vueReuse from 'unplugin-vue-reuse-template/vite'

  


export default {

  plugins: [vue(), vueReuse()]

}

③ 定义全局模板

vue 复制代码
<!-- src/components/TemplateBank.vue -->

<template>

  <template $btn>

    <button class="btn"><slot /></button>

  </template>

  <template $card>

    <div class="card"><slot name="title"/><slot/></div>

  </template>

</template>

<style>

.btn{@apply px-4 py-2 bg-blue-500 text-white rounded}

.card{@apply border rounded p-4 shadow}

</style>

  

main.js 里确保被预加载

javascript 复制代码
import '@/components/TemplateBank.vue'

④ 任意组件直接调用

vue 复制代码
<template>

  <template $use="$btn">提交</template>

  <template $use="$card">

    <template #title><h3>标题</h3></template>

    <p>内容</p>

  </template>

</template>

  

📊 小结

| 方式 | 范围 | 语法 | 插件 |

| --- | --- | --- | --- |

| createReusableTemplate | 当前组件 | Def/Reuse | 不需要 |

| unplugin-vue-reuse-template | 全局 | <template $use> | 需要

相关推荐
华仔啊2 小时前
面试都被问懵了?CSS 的 flex:1 和 flex:auto 真不是一回事!90%的人都搞错了
前端·javascript
前端康师傅3 小时前
JavaScript 函数详解
前端·javascript
金金金__3 小时前
antd v5 support React is 16 ~ 18. see https://u.ant.design/v5-for-19 for...
前端
用户4099322502123 小时前
如何用FastAPI玩转多模块测试与异步任务,让代码不再“闹脾气”?
后端·ai编程·trae
会豪3 小时前
工业仿真(simulation)--前端(二)-资源管理器
前端
云起SAAS3 小时前
贪吃蛇鱼小游戏抖音快手微信小程序看广告流量主开源
ai编程·贪吃蛇
@小红花3 小时前
从0到1学习Vue框架Day03
前端·javascript·vue.js·学习·ecmascript
前端与小赵3 小时前
vue3中 ref() 和 reactive() 的区别
前端·javascript·vue.js
魔云连洲4 小时前
Vue的响应式底层原理:Proxy vs defineProperty
前端·javascript·vue.js