Jiang's Tech Journal

Jiang's Tech Journal

首页
分类
关于
Login →
Jiang's Tech Journal

Jiang's Tech Journal

首页 分类 关于
Login
  1. Home
  2. 前端
  3. 【Vue】VueUse 中 createReusableTemplate 的妙用

【Vue】VueUse 中 createReusableTemplate 的妙用

0
  • 前端
  • Published at 2025-12-29
  • Read 19 times
Jiang
Jiang
Table of Contents
No Table of Contents

在 Vue 3 开发中,虽然推荐使用模板语法,但在封装高阶组件或使用特定 UI 库(如 Naive UI、Element Plus、Ant Design Vue)的表格组件时,我们往往需要编写 Render 函数(h 函数)或使用 JSX/TSX 来处理复杂的自定义列渲染。

对于不熟悉渲染函数 API 的开发者来说,直接手写嵌套的 h 函数不仅开发效率低,代码的可读性和维护性也极差。本文将介绍如何利用 VueUse 的 createReusableTemplate 工具,优雅地解决这一痛点。

痛点分析:嵌套地狱

以 Naive UI 的数据表格组件 NDataTable 为例,假设我们需要在“操作”列中渲染两个带有二次确认气泡框(Popover)的按钮:“编辑”和“删除”。

如果使用原生的 h 函数编写,代码结构如下:

// ❌ 传统的 h 函数写法:嵌套层级深,阅读困难
import { h } from 'vue'
import { NButton, NDataTable, NPopover, NSpace } from 'naive-ui'

const columns = [
  { title: '名字', key: 'name' },
  {
    title: '操作',
    key: 'action',
    render: (row) => {
      // 创建一个 NSpace 包裹两个按钮
      return h(NSpace, {}, [
        // 第一个 Popover:编辑
        h(
          NPopover,
          { trigger: 'hover' },
          {
            default: () => '点击编辑该行数据',
            trigger: () => h(NButton, { size: 'small', type: 'primary' }, { default: () => '编辑' })
          }
        ),
        // 第二个 Popover:删除
        h(
          NPopover,
          { trigger: 'hover' },
          {
            default: () => '点击删除该行数据',
            trigger: () => h(NButton, { size: 'small', type: 'error' }, { default: () => '删除' })
          }
        )
      ])
    }
  }
]

可以看到,即使是这样一个简单的需求,代码的嵌套层级也已经非常深,且难以直观地看出 DOM 结构。随着业务逻辑的增加(如添加点击事件、动态显隐等),这段代码将变得难以维护。

解决方案:createReusableTemplate

createReusableTemplate 是 VueUse 提供的一个实用工具。它的核心思想是:允许你在 <template> 块中使用熟悉的 HTML 语法定义一段 UI 结构,然后将其转换为一个可以在 JS/TS 中引用的组件。

1. 创建模板容器

首先,我们通过 createReusableTemplate 创建一对组件:Define(用于定义内容)和 Use(用于渲染内容)。

<script setup lang="ts">
import { createReusableTemplate } from '@vueuse/core'

// 定义泛型 { row: any } 以获得类型提示
const [DefineActionTemplate, UseActionTemplate] = createReusableTemplate<{ row: any }>()
</script>

2. 在 Template 中编写 UI

接下来,我们利用 DefineActionTemplate 组件,使用标准的 Vue 模板语法来编写操作列的结构。这里可以毫无障碍地使用 v-if、v-for、@click 等指令。

<template>
  <div>
    <!-- 定义可复用模板:通过 v-slot 接收 row 数据 -->
    <DefineActionTemplate v-slot="{ row }">
      <NSpace>
        <!-- 编辑按钮 -->
        <NPopover trigger="hover">
          <template #trigger>
            <NButton size="small" type="primary" @click="handleEdit(row)">编辑</NButton>
          </template>
          <span>点击编辑:{{ row.name }}</span>
        </NPopover>
        
        <!-- 删除按钮 -->
        <NPopover trigger="hover">
          <template #trigger>
            <NButton size="small" type="error" @click="handleDelete(row)">删除</NButton>
          </template>
          <span>确认删除该行吗?</span>
        </NPopover>
      </NSpace>
    </DefineActionTemplate>

    <!-- 表格组件:像往常一样使用 -->
    <NDataTable :columns="columns" :data="data" />
  </div>
</template>

3. 在 Render 函数中引用

最后,回到 columns 的定义。现在我们不需要手写复杂的 DOM 结构了,只需要通过 h 函数渲染我们在模板中定义的 UseActionTemplate 组件,并将 row 数据传递给它即可。

const columns = [
  { title: '名字', key: 'name' },
  {
    title: '操作',
    key: 'action',
    // ✅ 优化后的写法:逻辑清晰,代码简洁
    render: (row) => h(UseActionTemplate, { row })
  }
]

方案优势

  1. 降低心智负担:开发者可以继续使用熟悉的模板语法编写复杂的 UI 结构,无需在脑中将 HTML 翻译成 h 函数或 JSX。
  2. 提升可维护性:视图结构(Template)与数据配置(JS)分离,结构更加清晰,修改样式或添加交互变得非常简单。
  3. 类型安全:通过泛型支持,在模板中使用 row 数据时可以获得完整的类型提示。
  4. 无缝集成:不需要引入构建步骤或配置 JSX/TSX 环境,纯 Vue 运行时即可支持。

适用场景

  • 使用 Naive UI、Ant Design Vue 等组件库的 NDataTable / Table 组件,需要自定义复杂列渲染时。
  • 需要在组件内部多次复用同一段复杂的 DOM 结构,但又不想将其拆分为独立的 .vue 文件时。
  • 需要将模板结构传递给第三方库的回调函数时。

💡 小贴士:虽然 TSX 也是解决此类问题的强力工具,但 createReusableTemplate 提供了一种更“Vue Native”的轻量级替代方案,特别适合那些不想在项目中引入 TSX 依赖的团队。

Related Posts

OpenCode 接入 Figma MCP:无需安装 fork 的 OAuth 解决办法

在 OpenCode 中接入 Figma 的远程 MCP 服务时,如果 OAuth 授权流程无法正常完成,可以通过手动注册一个 Figma MCP OAuth 客户端来绕过问题。这个方法不需要安装第三方 fork,核心思路是: 向 Figma 的 MCP OAuth 注册接口申请客户端凭据。 把返回

【Vue】VueUse 中 createReusableTemplate 的妙用

在 Vue 3 开发中,虽然推荐使用模板语法,但在封装高阶组件或使用特定 UI 库(如 Naive UI、Element Plus、Ant Design Vue)的表格组件时,我们往往需要编写 Render 函数(h 函数)或使用 JSX/TSX 来处理复杂的自定义列渲染。 对于不熟悉渲染函数 AP

【Vue】 组件内模板复用技巧:createReusableTemplate

在 Vue 组件开发中,我们经常遇到部分模板内容需要在同一组件内多次复用的场景。传统的解决方案如提取子组件、v-for 循环或直接复制粘贴,在某些简单场景下可能显得过于繁琐或冗余。 本文介绍一种利用 Vue 3 组合式 API 和渲染函数特性实现的“局部模板复用”技巧,类似于模板引擎中的“宏(Mac

【Vue】组件二次封装技巧

日常任务开发过程中避免不了进行 UI 组件库部分组件的二次封装使用,记录下长期开发过程中积累的一些经验和网络学习的新技巧,组件二次封装需要解决的无非就是属性 props 如何透传出去,如何复用原有组件的插槽,以及如何调用原组件暴露的方法,这里以比较热门的 UI 框架 Element Plus 为例。

【vue-admin-kit】配置驱动的 Vue 3 后台管理组件工具套件

📖 在线文档:https://vue-admin-kit.jiang.in/ 前言 在企业级后台管理系统开发中,CRUD 页面占据了大量的开发工作。搜索表单、数据表格、新增/编辑弹窗、详情展示……这些重复性的工作不仅耗时,还容易产生不一致的代码风格。 vue-admin-kit 正是为解决这一痛点

[CSS] 移除元素焦点状态

padding: '0' - 移除内边距 border: 'none' - 移除边框 outline: 'none' - 移除焦点时的轮廓线(这是关键!) boxShadow: 'none' - 移除可能的阴影效果

Table of Contents
No Table of Contents
Copyright © 2024 your company All Rights Reserved. Powered by Halo.