Vue3复用组件怎么使用
今天golang学习网给大家带来了《Vue3复用组件怎么使用》,其中涉及到的知识点包括等等,无论你是小白还是老手,都适合看一看哦~有好的建议也欢迎大家在评论留言,若是看完有所收获,也希望大家能多多点赞支持呀!一起加油学习~
前言
无论是 vue 还是 react,当遇到多处重复代码的时候,我们都会想着如何复用这些代码,而不是一个文件里充斥着一堆冗余代码。
实际上,vue 和 react 都可以通过抽组件的方式来达到复用,但如果遇到一些很小的代码片段,你又不想抽到另外一个文件的情况下,相比而言,react 可以在相同文件里面声明对应的小组件,或者通过 render function 来实现,如:
const Demo: FC<{ msg: string}> = ({ msg }) => { returndemo msg is { msg }} const App: FC = () => { return ( <>> ) }
/** render function的形式 */ const App: FC = () => { const renderDemo = (msg : string) => { returndemo msg is { msg }} return ( <> {renderDemo('msg1')} {renderDemo('msg2')} > ) }
但对于 .vue
模板 来说,没法像 react 一样在单个文件里面声明其他组件,如果你要复用代码,那就只能通过抽离组件的方式。
可是啊可是啊!就如上面 Demo 组件,就零零散散两三行代码,抽成一个组件你又觉得没太必要,那唯一的解决方案就是 CV 大法?(当然,如果是诸如 list 之类的,可以用 v-for 代码,但这里介绍的不是这种场景)
我知道你很急,但你先别急。如果我们可以通过在组件范围内将要复用的模板圈起来,跟 vue 说,喂,这代码是我圈起来的,因为我有好几处要用到,虽然目前你看起来好像不支持这功能,不过,没事,你实现不了的,我来实现
那大致实现方案就是这样子啦:
... Foo: {{ msg }} xxx yyy
可是,这种方案究竟如何实现呢?毕竟牛都已经吹上天了,实现不了也要硬着头皮折腾。好了,不卖关子,antfu 大佬实际上已经实现了,叫做createReusableTemplate
,且放到 VueUse 里面了,具体可以点击文档看看。
用法
通过 createReusableTemplate 拿到定义模板和复用模板的组件
然后在你要复用代码的地方,将其用DefineTemplate
包起来,之后就可以通过ReuseTemplate
在单文件 template 的任意地方使用了:
...
⚠️ DefineTemplate 务必在 ReuseTemplate 之前使用
我们看到,createReusableTemplate 返回了一个 Tuple,即 define 和 reuse 的组件对,然后,通过上面的例子就可以在单文件里面复用多处代码了。
还有,实际上还可以通过对象解构的方式返回一个 define 和 reuse(很神奇吧,这篇文章就不展开了,有兴趣下次再分享下),用法同上,例子如下
Foo: {{ msg }} Bar: {{ msg }} Biz: {{ msg }} This is a slot from Reuse This is another one
真是神奇,那咋实现呢
上面我们介绍了用法,相信应该没人看不懂,上手成本确实为 0,那接下来我们一起看看是如何实现的。
我们知道,Vue3 定义组件除了通过 script setup 的方式之外, 还可以通过defineComponent
的方式
const Demo = defineComponent({ props: { ..., }, setup(props, { attrs, slots }) { return () => { ... } } })
然后我们观察下是如何定义模板的
Foo: {{ msg }}
好像似曾相识?v-slot?,诶,卧槽,这不是插槽吗!还有,模板代码看起来就是放在默认插槽的。
好,我们接下来看下如何实现 Define 的功能。
实现 Define
我们刚才说,模板是定义在默认插槽里面,那我们可以定义个局部变量 render,之后当在 template 里面使用 Define 时会进入 setup,这时候拿到 slot.default,放在 render 上不就好?,代码如下
let render: Slot | undefined const Define = defineComponent({ setup(props, { slots, }) { return () => { /** 这里拿到默认插槽的渲染函数 */ render = slots.default } } })
对的,就是这么简单,对于 Define 来说,核心代码就是这两三行而已
实现 Reuse
上面拿到 render function 了,那我们在使用 Reuse 的地方,将所得到的 v-slot、attrs 等传给 render 不就好?
同样,当我们在 template 使用 Reuse 的时候,就会进入 setup,然后将得到的参数都传给 render,并 return render 的结果即可
const reuse = defineComponent({ setup(_, { attrs, slots }) { return () => { /** * 没有render,有两种可能 * 1. 你没Define * 2. Define写在Reuse后面 **/ if (!render && process.env.NODE_ENV !== 'production') throw new Error(`[vue-reuse-template] Failed to find the definition of template${name ? ` "${name}"` : ''}`) return render?.({ ...attrs, $slots: slots }) } }, })
上面的 attrs 也就是你在 Reuse 上传的 prop 了
而为啥还要传个$slots?
上面实际上有个例子,模板里面还可以通过动态组件
的方式来拿到插槽的真正内容
Biz: {{ msg }} This is a slot from Reuse This is another one
当然,不只默认插槽啦,其他具名插槽都可以
Biz: {{ msg }} 我是 reuse1的headerThis is a slot from Reuse 我是 reuse1的headerThis is another one
具体怎么玩出花,你来定~
类型支持,提升开发体验
我们定义了模板,但模板接收什么参数,传入什么参数,你得告诉我对不对,如果没有类型的提示,那么开发体验会极其糟糕,不过,不用担心,大佬这些都考虑好了。
createReusableTemplate 支持泛型参数,也就是说你要复用的模板需要什么参数,只需要通过传入对应类型即可,比如你有个 msg,是 string 类型,那么用法如下
const [DefineFoo, ReuseFoo] = createReusableTemplate<{ msg: string }>()
然后你就会发现,DefineFoo, ReuseFoo 都会对应的类型提示了
添加类型支持
我们上面说是用 defineComponent 得到 Define 和 Reuse,而 defineComponent 返回的类型就是 DefineComponent 呀
type DefineComponent
假设模板参数类型为 Bindings 的话,那么对于 Reuse 来说,其既支持传参,也支持添加插槽内容,所以类型如下
type ReuseTemplateComponent< Bindings extends object, Slots extends Record, /** Bindings使之有类型提示 */ > = DefineComponent & { /** 插槽相关 */ new(): { $slots: Slots } }
而对于 Define 类型来说,我们知道其 v-slot 也有对应的类型,且能通过$slots 拿到插槽内容,所以类型如下
type DefineTemplateComponent< Bindings extends object, Slots extends Record, Props = {}, > = DefineComponent & { new(): { $slots: { default(_: Bindings & { $slots: Slots }): any } } }
小结一下
ok,相信我开头说的看懂只需要 1 分钟不到应该不是吹的,确实实现很简单,但功能又很好用,解决了无法在单文件复用代码的问题。
我们来小结一下:
通过 Define 来将你所需要复用的代码包起来,通过 v-slot 拿到传过来的参数,同时支持渲染其他插槽内容
通过 Reuse 来复用代码,通过传参渲染出不同的内容
为了提升开发体验,加入泛型参数,所以 Define 和 Reuse 都有对应的参数类型提示
要记住使用条件,Define 在上,Reuse 在下,且不允许只使用 Reuse,因为拿不到 render function,所以会报错
加个彩蛋吧
实际上多次调用 createReusableTemplate 得到相应的 DefineXXX、ReuseXXX 具有更好的语义化)
也就是说,我不想多次调用 createReusableTemplate 了,直接让 define 和 reuse 支持 name 参数(作为唯一的 template key),只要两者都有相同的 name,那就意味着它们是同一对
如何魔改
实际上也很简单,既然要支持 prop name
来作为唯一的 template key,那 define 和 reuse 都添加 prop name 不就好?
const define = defineComponent({ props { name: String } }) const reuse = defineComponent({ props { name: String } })
然后之前不是有个 render 局部变量吗?因为现在要让一个 Define 支持通过 name 来区分不同的模板,那么我们判断到传入了 name,就映射对应的的 render 不就好?
这里我们通过 Map 的方式存储不同 name 对应的 render,然后 define setup 的时候存入对应 name 的 render,reuse setup 的时候通过 name 拿到对应的 render,当然如果没传入 name,默认值是 default,也就是跟没有魔改之前是一样的
const renderMap = new Map() const define = defineComponent({ props: { /** template name */ name: String, }, setup(props, { slots }) { return () => { const templateName: string = props.name || 'default' if (!renderMap.has(templateName)) { // render = slots.default renderMap.set(templateName, slots.default) } } }, }) const reuse = defineComponent({ inheritAttrs: false, props: { name: String, }, setup(props, { attrs, slots }) { return () => { const templateName: string = props.name || 'default' const render = renderMap.get(templateName) if (!render && process.env.NODE_ENV !== 'production') throw new Error(`[vue-reuse-template] Failed to find the definition of template${templateName}`) return render?.({ ...attrs, $slots: slots }) } }, })
到这里,我们也就讲完了《Vue3复用组件怎么使用》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于Vue3的知识点!

- 上一篇
- 无法从 MongoDB 读取类型为“strfmt.DateTime”的 time_stamp

- 下一篇
- mac上苹果id登不上?
-
- 文章 · 前端 | 4小时前 |
- JavaScript中IntersectionObserverAPI的使用技巧
- 447浏览 收藏
-
- 文章 · 前端 | 5小时前 |
- JavaScript本地存储(localStorage)实战攻略
- 309浏览 收藏
-
- 文章 · 前端 | 5小时前 |
- Vue.jsCompositionAPI与OptionsAPI使用对比
- 420浏览 收藏
-
- 文章 · 前端 | 6小时前 |
- JavaScriptArray.filter用法详解与实例
- 383浏览 收藏
-
- 文章 · 前端 | 6小时前 | 鼠标事件 跨浏览器兼容性 拖拽功能 transform属性 触摸设备支持
- JavaScript拖拽功能实现技巧与代码示例
- 159浏览 收藏
-
- 文章 · 前端 | 7小时前 | 异步操作 生成器函数 async/await yield 无限序列
- JavaScript生成器函数创建终极攻略
- 161浏览 收藏
-
- 文章 · 前端 | 7小时前 |
- 前端开发CSS悬停内缩并显示图标技巧
- 460浏览 收藏
-
- 文章 · 前端 | 7小时前 |
- JavaScript如何将数据存入LocalStorage?
- 327浏览 收藏
-
- 文章 · 前端 | 7小时前 | TypeScript 类型转换 类型检查 特殊情况 复杂数据结构
- JavaScript搞定类型错误的终极攻略
- 119浏览 收藏
-
- 文章 · 前端 | 7小时前 | JavaScript 时间复杂度 快速排序 原地排序 基准元素
- JavaScript快速排序算法实现详解
- 372浏览 收藏
-
- 文章 · 前端 | 8小时前 |
- JavaScript中ShadowDOM使用技巧揭秘
- 335浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- AI Make Song
- AI Make Song是一款革命性的AI音乐生成平台,提供文本和歌词转音乐的双模式输入,支持多语言及商业友好版权体系。无论你是音乐爱好者、内容创作者还是广告从业者,都能在这里实现“用文字创造音乐”的梦想。平台已生成超百万首原创音乐,覆盖全球20个国家,用户满意度高达95%。
- 26次使用
-
- SongGenerator
- 探索SongGenerator.io,零门槛、全免费的AI音乐生成器。无需注册,通过简单文本输入即可生成多风格音乐,适用于内容创作者、音乐爱好者和教育工作者。日均生成量超10万次,全球50国家用户信赖。
- 21次使用
-
- BeArt AI换脸
- 探索BeArt AI换脸工具,免费在线使用,无需下载软件,即可对照片、视频和GIF进行高质量换脸。体验快速、流畅、无水印的换脸效果,适用于娱乐创作、影视制作、广告营销等多种场景。
- 23次使用
-
- 协启动
- SEO摘要协启动(XieQiDong Chatbot)是由深圳协启动传媒有限公司运营的AI智能服务平台,提供多模型支持的对话服务、文档处理和图像生成工具,旨在提升用户内容创作与信息处理效率。平台支持订阅制付费,适合个人及企业用户,满足日常聊天、文案生成、学习辅助等需求。
- 23次使用
-
- Brev AI
- 探索Brev AI,一个无需注册即可免费使用的AI音乐创作平台,提供多功能工具如音乐生成、去人声、歌词创作等,适用于内容创作、商业配乐和个人创作,满足您的音乐需求。
- 25次使用
-
- 优化用户界面体验的秘密武器:CSS开发项目经验大揭秘
- 2023-11-03 501浏览
-
- 使用微信小程序实现图片轮播特效
- 2023-11-21 501浏览
-
- 解析sessionStorage的存储能力与限制
- 2024-01-11 501浏览
-
- 探索冒泡活动对于团队合作的推动力
- 2024-01-13 501浏览
-
- UI设计中为何选择绝对定位的智慧之道
- 2024-02-03 501浏览