Vue 也能复用模板了

news2024/11/23 1:09:07

文章目录

  • Vue 也能复用模板了
    • 1. 怎么用
      • 1.1 基本使用
      • 1.2 传递参数
    • 2. 怎么实现的
    • 3. 注意事项
    • 4. 未来发展

Vue 也能复用模板了

相信很多使用 Vue 的同学会遇到这样一个问题:

“组件里有几个部分的模板(html 结构)是相同的,要想复用的话, 便只能将其抽成一个子组件,但因为要传递属性和监听事件等,总觉得麻烦,这时候就会想, 要是能像 React 那样能在组件中直接复用模板就好了。”

譬如下面这个例子:

<template>
  <dialog v-if="showInDialog">
    <!-- 模板内容 -->
  </dialog>
  <div v-else>
    <!-- 与上相同的模板内容 -->
  </div>
</template>

要想复用,就得把这块儿模板抽离成子组件。这很合理,但这样做也会有些不足, 子组件无法访问父组件的上下文,即变量、事件都不能访问到,需要我们通过属性(props)、事件绑定(v-bind) 的方式来使得子组件得以访问。

子组件的方式是可以,没毛病,可是当抽离的子组件(可复用部分)仅当前组件多次使用时,会发现属性传递、事件绑定以及事件触发这一系列过程都没那么优雅了。

React 这时候笑了,我天然支持好吧

那有没有办法可以直接在当前组件实现模板的复用呢?

在这里插入图片描述

**答案是必须的。**

这个问题其实早在 2022 年就已经在 vuejs/core 的 issue 被大家提出并讨论,但一直没有一个好的解决方案,直到 2 天前,超级大神 antfu 提出了一个非常巧妙的方案——“vue-reuse-template”,这也是今天的主题。

vue-reuse-template 用一个很优雅巧妙的思想解决了模板复用的问题,一起来看看大神之作吧。

1. 怎么用

1.1 基本使用

用法非常的简单,一个定义,一个使用,就像使用变量一样简单。

<script setup>
import { createReusableTemplate } from 'vue-reuse-template'

const [DefineTemplate, ReuseTemplate] = createReusableTemplate()
</script>

<template>
  <DefineTemplate>
    <!-- something complex -->
  </DefineTemplate>

  <dialog v-if="showInDialog">
    <ReuseTemplate />
  </dialog>
  <div v-else>
    <ReuseTemplate />
  </div>
</template>
  • DefineTemplate 内部包裹需要复用的模板,DefineTemplate 不会渲染内容,这就相当于变量的定义阶段。

  • ReuseTemplateDefineTemplate 成对出现,ReuseTemplate会渲染出模板内容,这就相当于变量的使用阶段。

1.2 传递参数

因为插槽的机制,所以 ”待复用模板“ 的作用域就是当前组件,那么组件的变量、事件都可以直接使用。这里只是为了展示如果传递额外参数。

<template>
  <DefineTemplate v-slot="{ data, msg, anything }">
    <div>{{ data }} passed from usage</div>
  </DefineTemplate>

  <ReuseTemplate :data="data" msg="The first usage" />
  <ReuseTemplate :data="anotherData" msg="The second usage" />
  <ReuseTemplate v-bind="{ data: something, msg: 'The third' }" />
</template>

欲知更多用法,传送门在此。

2. 怎么实现的

“哇塞,这有点意思呀,它是怎么实现的呀!不会很复杂吧!”,这是我看到后的第一想法。

实现方式非常的巧妙,包含类型,整个代码也就 75 行,主函数也就 30 行左右,这么简单吗?一起来看看它是如何实现的吧!

先总结:

  1. 利用 插槽 获取 “待复用模板” —— define
  2. 利用 闭包 所记录的插槽实现复用 —— reuse
export function createReusableTemplate<
  Bindings extends object,
  Slots extends Record<string, Slot | undefined> = Record<string, Slot | undefined>,
>(name?: string) {
  // render 用于记录 “待复用模板”
  let render: Slot | undefined
	
  // 定义组件:组件作为 “待复用模板” 外层,此时,插槽的内容,即 “待复用模板” 用 render 记录下来
  const define = defineComponent((_, { slots }) => {
    return () => {
      // 这里没有 return 任何内容,所以不会渲染
      render = slots.default
    }
  })
	
  // 复用组件:直接渲染 render 以达到复用的效果
  const reuse = defineComponent({
    inheritAttrs: false,
    setup(_, { attrs, slots }) {
      return () => {
        return render?.({ ...attrs, $slots: slots })
      }
    },
  })
	
  // 导出 定义组件 和 复用组件
  return makeDestructurable(
    { define, reuse },
    [define, reuse] as const,
  )
}

这里来详细说明:

  1. render 变量

    render 用于记录 “待复用模板”

  2. define 函数(组件)

    通过 defineComponent 函数直接生成组件,可以将其理解为它就是一个子组件(自定义组件),将 “待复用模板” 作为其插槽,组件渲染时,会执行里面的 render = slots.default,如此,“待复用模板” 便被记录了下来。

    相当于说 “待复用模板” 作为了插槽给记录了下来

    而且,define 函数没有 return 任何内容,所以不会渲染。

  3. reuse 函数(组件)

    同样通过 defineComponent 函数直接生成组件,内部渲染的是什么呢?就是 define 函数中所记录的 render,如此,便实现了复用。

    这里就是闭包

  4. 参数传递

    render 所记录的就是一个插槽,所以参数的传递与插槽完全一致。

  5. 作用域(上下文)

    插槽所在的作用域就是父组件的作用域,所以,“待复用模板”可直接使用组件的变量、事件等。大神把插槽的机制用得是淋漓尽致呀!

    哇,这多香呀

整个思路没有一个是超纲知识,如此简单却如此优雅,所以大神还是大神呀!哈哈!

3. 注意事项

  1. 不要滥用

    很好用,但请不要滥用它。

    如果一个复用的部分仅在当前组件使用并且在能保证维护性的前提下,使用它很香。除此之外,不论是从复用的角度还是项目维护成本的角度去看,该抽离成子组件的时候建议还是抽离。

  2. 性能不用担心

    从实现的就可以看出,复用的过程开销很小,基本不需要担心它对性能的影响。

4. 未来发展

因为场景确实会遇到,而且并不算罕见;加之社区很多同学都在反应。

在这里插入图片描述

所以未来官方有可能会直接支持的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/422468.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用线性回归构建波士顿房价预测模型

使用线性回归构建波士顿房价预测模型 描述 波士顿房价数据集统计了波士顿地区506套房屋的特征以及它们的成交价格&#xff0c;这些特征包括周边犯罪率、房间数量、房屋是否靠河、交通便利性、空气质量、房产税率、社区师生比例&#xff08;即教育水平&#xff09;、周边低收入…

前馈PID控制(热交换器/反应釜温度控制)

如何利用PID进行温度控制请参看下面博客文章: 博途PID 1200/1500PLC PID_Compact比例作用权重b微分作用权重c解读(PI-D控制器 I-PD控制器)_RXXW_Dor的博客-CSDN博客很多人会问PLC自带的PID指令和我们自己设计的PID有什么区别,这个问题要看你和什么PID控制器作对比,PID负反…

python真的如此好吗?

作为一名合格的&#xff08;准&#xff09;程序员&#xff0c;必做的一件事是关注编程语言的热度&#xff0c;编程榜代表了编程语言的市场占比变化&#xff0c;它的变化更预示着未来的科技风向和机会&#xff01; Python霸占榜首 只因它真的很强 Python&#xff0c;年龄可能比…

2023年的深度学习入门指南(5) - HuggingFace Transformers库

2023年的深度学习入门指南(5) - HuggingFace Transformers库 这一节我们来学习下预训练模型的封装库&#xff0c;Hugging Face的Transformers库的使用。Hugging Face的库非常活跃&#xff0c;比如支持LLaDA大规型的类&#xff0c;是在本文开始写作的前一天发布的。 库新到这种…

JavaWeb——锁策略, cas和synchronized优化过程

目录 一、锁策略 1、悲观锁和乐观锁 2、轻量级锁和重量级锁 3、自旋锁和挂起等待锁 4、互斥锁和读写锁 5、可重入锁和不可重入锁 6、公平锁和非公平锁 二、cas和synchronized 优化过程 1、CAS&#xff08;compare and swap&#xff09; &#xff08;1&#xff09;、原…

企业网站架构部署与优化

系列文章目录 文章目录系列文章目录一、LAMP概述与简介1.LAMP2.各组件的主要作用如下&#xff1a;二、1.编译安装Apache http服务2.编译安装 Mysql 服务3.编译安装 PHP 解析环境总结一、LAMP概述与简介 1.LAMP LAMP架构是目前成熟的企业网站应用模式之一&#xff0c;指的是协…

如何高效建立知识库?

建立知识库是为了更好地管理和传承知识&#xff0c;提高团队的效率和成果。在建立知识库的过程中&#xff0c;需要注意一些关键点&#xff0c;以确保知识库的高效性和可持续性。本文将介绍如何高效建立知识库以及需要注意的事项。 一、建立知识库的步骤 1.明确知识库的目的和…

SpringBoot 默认数据库连接池 HikariCP

目录 引言 1、问题描述 2、SpringBoot默认的数据库连接池 3、HikariCP是什么 4、测试依赖 5、配置文件 5.1、数据库连接参数 5.2、连接池数据基本参数 5.3、连接检查参数 5.4、事务相关参数 5.5、JMX参数 6、HikariCP源码浅析 6.1、HikariConfig--连接池配置的加载…

Observability:使用 OpenTelemetry 和 Elastic 监控 OpenAI API 和 GPT 模型

作者&#xff1a;David Hope ChatGPT 现在很火&#xff0c;它打破了互联网。 作为 ChatGPT 的狂热用户和 ChatGPT 应用程序的开发者&#xff0c;我对这项技术的可能性感到无比兴奋。 我看到的情况是&#xff0c;基于 ChatGPT 的解决方案将呈指数级增长&#xff0c;人们将需要监…

Shiro概述

文章目录1.权限的管理1.1 什么是权限管理1.2 什么是身份认证1.3 什么是授权2.Shiro概述2.1 什么是Shiro2.2 Shiro 与 SpringSecurity 的对比2.3 基本功能3.shiro的核心架构4.shiro中的认证4.1 认证4.2 shiro中认证的关键对象4.3 身份认证流程4.4.登录认证实例4.5 自定义Realm5.…

Python标记数组的连通域

文章目录连通域标记structure参数操作连通域定位连通域连通域标记 通过label函数&#xff0c;可以对数组中的连通区域进行标注&#xff0c;效果如下 from scipy.ndimage import label import numpy as np a np.array([[0,0,1,1,0,0],[0,0,0,1,0,0],[1,1,0,0,1,0],[0,0,0,1,0…

虚拟机里安装ubuntu-23.04-beta-desktop-amd64,开启SSH(换源、备份),配置中文以及中文输入法

一、下载 官网 清华镜像站(推荐) 二、配置虚拟机 【自定义】 点击“下一步”&#xff0c;此处【默认】&#xff0c;再点击“下一步”。 点击“稍后安装操作系统”&#xff0c;再点击“下一步”。 点击“Linux(L)”&#xff0c;版本选择【Ubuntu 64 位】&#xff0c;再点击…

轻量级网页RSS阅读器selfoss

什么是 selfoss &#xff1f; selfoss 是一个多用途的 RSS 阅读器和提要聚合 Web 应用程序。它使您可以在一个地方轻松关注来自不同网站、社交网络和其他平台的更新。它是用 PHP 编写的&#xff0c;基本上可以让您在任何地方运行它。 安装 在群晖上以 Docker 方式安装。 在注…

【前沿技术】问答pk【ChatGPT Vs Notion AI Vs BAT AI 】

目录 写在前面 问题&#xff1a; 1 ChatGPT 1.1 截图 ​1.2 文字版 2 Notion AI 2.1 截图 2.2 文字版 3 BAT AI 3.1 截图 3.2 文字版 总结 序言 所有幸运和巧合的事&#xff0c;要么是上天注定&#xff0c;要么是一个人偷偷的在努力。 突发奇想&#xff0c;问三个…

机器学习---聚类算法

目录【写在前面】1、确认安装有scikit-learn库2、使用 make _ classification ()建立数据集3、使用模型进行分类头文件汇总亲和力传播聚合聚类BIRCH 聚类DBSCAN【本人的毕业设计系统中有用到】K-均值高斯混合模型【写在最后】【写在前面】 sklearn和scikit-learn&#xff1a; …

软件测试需要学什么

软件测试近些年也是比较热门的行业&#xff0c;薪资高、入门门槛低&#xff0c;让很多开发人员想纷纷加入软件开发这个行业&#xff0c;想要成为这一岗位的一员&#xff0c;想要进入软件测试行业&#xff0c;他们需要学习什么呢&#xff1f; 软件测试需要学习的还挺多的&#…

Flowable开源版和Flowable商业版有什么区别?

Flowable除了提供开源版本flowable-engine&#xff0c;它还提供了一系列基于Flowable引擎的快速、现代和完全可定制的企业产品&#xff08;商业收费&#xff09;&#xff1a;Flowable Work、Flowable Orchestrate和Flowable Engage。Flowable的开源版本和商业版本有什么区别&am…

【产线事故】分享生产线事故发生的一次OOM

文章目录前言OutOfMemoryError出现的原因常见堆内存溢出的几种情况现象分析Mybatis源码分析情景复现总结前言 继上次线上CPU出现了报警&#xff0c;这次服务又开始整活了&#xff0c;风平浪静了没几天&#xff0c;看生产日志服务的运行的时候&#xff0c;频繁的出现OutOfMemor…

接口自动化测试如何做?测试老鸟总结,接口测试数据构造大全......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 接口参数的数据获取…

Linux复习 / 线程相关----线程概念与控制 QA梳理

文章目录前言Q&A线程概念Q&#xff1a;线程和进程的区别&#xff1f;&#xff08;为什么要有线程&#xff0c;从进程的角度说明这个问题&#xff09;Q&#xff1a;Linux是如何设计线程的&#xff1f;Q&#xff1a;学习了线程后&#xff0c;你能说说进程和线程最大的区别是什…