开发提速?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> | 需要

相关推荐
Filotimo_1 小时前
2.CSS3.(2).html
前端·css
yinuo2 小时前
uniapp微信小程序华为鸿蒙定时器熄屏停止
前端
gnip3 小时前
vite中自动根据约定目录生成路由配置
前端·javascript
前端橙一陈5 小时前
LocalStorage Token vs HttpOnly Cookie 认证方案
前端·spring boot
~无忧花开~5 小时前
JavaScript学习笔记(十五):ES6模板字符串使用指南
开发语言·前端·javascript·vue.js·学习·es6·js
泰迪智能科技015 小时前
图书推荐丨Web数据可视化(ECharts 5)(微课版)
前端·信息可视化·echarts
CodeCraft Studio5 小时前
借助Aspose.Email,使用 Python 读取 Outlook MSG 文件
前端·python·outlook·aspose·email·msg·python读取msg文件
RainbowSea5 小时前
9. Spring AI 当中对应 MCP 的操作
java·spring·ai编程
RainbowSea6 小时前
10. Spring AI + RAG
java·spring·ai编程
zzywxc7876 小时前
AI 开发工具全景指南:从编码辅助到模型部署的全流程实践
大数据·人工智能·低代码·机器学习·golang·自动化·ai编程