Vue 也能复用模板了
文章目录
- 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
不会渲染内容,这就相当于变量的定义阶段。ReuseTemplate
与DefineTemplate
成对出现,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 行左右,这么简单吗?一起来看看它是如何实现的吧!
先总结:
- 利用 插槽 获取 “待复用模板” ——
define
- 利用 闭包 所记录的插槽实现复用 ——
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,)
}
这里来详细说明:
render
变量render
用于记录 “待复用模板”define
函数(组件)通过
defineComponent
函数直接生成组件,可以将其理解为它就是一个子组件(自定义组件),将 “待复用模板” 作为其插槽,组件渲染时,会执行里面的render = slots.default
,如此,“待复用模板” 便被记录了下来。相当于说 “待复用模板” 作为了插槽给记录了下来
而且,
define
函数没有 return 任何内容,所以不会渲染。reuse
函数(组件)同样通过
defineComponent
函数直接生成组件,内部渲染的是什么呢?就是define
函数中所记录的render
,如此,便实现了复用。这里就是闭包
参数传递
render
所记录的就是一个插槽,所以参数的传递与插槽完全一致。作用域(上下文)
插槽所在的作用域就是父组件的作用域,所以,“待复用模板”可直接使用组件的变量、事件等。大神把插槽的机制用得是淋漓尽致呀!
哇,这多香呀
整个思路没有一个是超纲知识,如此简单却如此优雅,所以大神还是大神呀!哈哈!
3. 注意事项
不要滥用
很好用,但请不要滥用它。
如果一个复用的部分仅在当前组件使用并且在能保证维护性的前提下,使用它很香。除此之外,不论是从复用的角度还是项目维护成本的角度去看,该抽离成子组件的时候建议还是抽离。
性能不用担心
从实现的就可以看出,复用的过程开销很小,基本不需要担心它对性能的影响。
4. 未来发展
因为场景确实会遇到,而且并不算罕见;加之社区很多同学都在反应。
所以未来官方有可能会直接支持的。
Vue 也能复用模板了相关推荐
- vue文件快速生成模板代码
vue文件快速生成模板代码 输入 vue 按 tab 键
- Vue.js 定义组件模板的七种方式
转载自 Vue.js 定义组件模板的七种方式 在 Vue 中定义一个组件模板,至少有七种不同的方式(或许还有其它我不知道的方式): 字符串 模板字面量 x-template 内联模板 render ...
- [vue] vue怎么改变插入模板的分隔符?
[vue] vue怎么改变插入模板的分隔符? optionMergeStrategies类型:{ [key: string]: Function }默认值:{}用法:Vue.config.option ...
- [vue] vue为什么要求组件模板只能有一个根元素?
[vue] vue为什么要求组件模板只能有一个根元素? '为什么只能有且只有一个根元素'于是我花了二十多分钟去找了一下答案......竟然没有找到答案....好的现在我来说说我的理解,如果有不对的地方 ...
- 【vue+springboot】excel模板下载、导入功能实现
基于VUE+SpringBoot实现excel模板下载.导入功能 背景 最近在工作中经常遇到批量导入的功能,而且前端还要提示导入成功几条.失败几条.哪一条数据重复.是哪一条导入的数据出现问题等,抽空写 ...
- vue实现下载EXCEL模板、导入EXCEL文件
vue实现下载EXCEL模板.导入EXCEL文件 在项目中很常见需要先下载模板,根据模板导入 下面展示一些 下载模板代码片段. 需要有一个下载模板的接口,点击下载触发函数,调用接口,返回下载地址 接口 ...
- vue下载excel表格模板和导入excel表格数据
vue下载excel表格模板和导入excel表格数据 vue制作excel表格模板给前端下载 vue制作excel表格模板给前端下载 最近有个需求,需要导入excel表格,并且还需要制作模板给用户下载 ...
- 关于Vue的就地复用
关于Vue的就地复用 这是第一次使用博客,就是想来记录一下自己碰到的一些问题以及解决方法,各位看官随意. 之前做项目的时候,要求对elementui的表格做拖拽排序,拖拽要做成只能通过拖拽最后一列的标 ...
- VUE+JAVA实现EXCEL模板下载
一.项目场景: VUE+JAVA实现EXCEL模板下载 二.功能背景 本人作为一个开发小白,今天接到一个小需求系统需要导入数据,也就十几个字段,我和老板说了,让客户一个一个去输入吧!然后我就被经理叫去 ...
最新文章
- php mssql 端口,MSSQL_SQL Server端口更改后的数据库连接方式,SQL Server端口,大家可以通过quot - phpStudy...
- 全球及中国甲苯甲酸行业投资决策与运营前景状况分析报告2022版
- Java正则表达式应用总结
- windebug的妙用
- MySql5.7 直接拷贝数据文件后出现table xxx doesn’t exist
- 百度网盘资源转迅雷下载正确打开方式!
- Windows.XP.x64.Pro.VOL(WINXP64位企业版)+正版序列号
- python傅里叶谐波分析_利用傅里叶谐波分析法的时序数据周期迭代辨识算法
- 聊聊大龄程序员的一条出路
- pxe kickstart无人值守自动化装机
- IPFS如何冲击我们熟知的网络世界
- 【CS224W】(task4/5)图嵌入表示学习(Deepwalk、Node2vec)更新中
- 使用uniapp框架搭建浙里办微应用(单点登录、埋点、适老化、RPC网关)
- 在Redis上通过Easy Message Queue扩展微服务
- LES-整车企业物料拉动系统的设计和实现
- requestFullscreen各种浏览器全屏模式的兼容方法记录和在TV项目的应用
- SolidWorks槽拉伸脱壳特征转钣金展开拆解
- Json转换利器Gson之实例五-实际开发中的特殊需求处理
- 安装cartographer时遇到编译问题
- 不分类工具:Win32 DiskImager安装教程