在前端开发中,弹窗是一个常见的需求,而Element UI框架中的el-dialog组件提供了弹窗的基本功能。然而,在实际开发中,我们可能会遇到一些需要定制化的需求,
比如需要对弹窗进行二次封装,以便在整个项目中统一管理弹窗的样式和行为。在这篇文章中,我将分享如何使用useDialog Hook来封装el-dialog,以实现更灵活、更易用的弹窗组件。
问题
在实际开发过程中,我们经常遇到一个场景:一个通用的购买组件需要在多个页面中使用。例如,在一个订阅服务的应用程序中,用户可能在订阅页面直接进行购买操作,同时,在其他页面浏览不同的服务时,根据业务逻辑判断是否需要购买,则需弹出同样的购买对话框提示用户。
为了实现这一功能,我们通常会采取以下步骤:
封装购买组件:首先创建一个通用的购买组件,以便在不同的页面和场景下复用。
在订阅页面渲染购买组件:将购买组件直接嵌入到订阅页面中。
在其他页面使用el-dialog展示购买组件:在不同的功能页面上,通过el-dialog来控制购买组件的显示,利用一个visible状态变量(通常是一个ref响应式变量)来动态控制对话框的弹出与关闭。
以上实现方式虽然可以满足功能需求,但随着该购买组件被越来越多的页面和功能所使用,维护起来就变得越加复杂和繁琐。我们必须在每个需要使用该组件的页面中重复编写控制显示隐藏的逻辑代码。
因此,一个明显的问题出现了:有没有更好的方法来简化这个过程?是否可以通过某种方式,使用一个单独的函数来全局控制购买组件的打开或关闭,从而减少代码重复并降低维护成本呢?
什么是useDialog Hook?
在Vue中,Hook是一种让你在函数式组件或者API中“钩入”Vue特性的方式。它们通常在合成API(Composition API
)中使用,这是Vue提供的一套响应式和可复用逻辑功能的集合。
例如,useDialog
Hook可能就是一个封装了<el-dialog>
组件基本功能的自定义Hook,并可能还提供了附加的特性以便更方便地在项目中管理&展示弹窗。
useDialog Hook的实现
我们需要达到的目标:
- 能够满足基础用法,传入
el-dialog
的基础属性以及默认slot显示的内容,导出openDialog
和closeDialog·
函数 - 支持
el-dialog
的事件配置 - 支持默认slot组件的属性配置
- 支持
el-dialog
其他slot
配置,如header
和footer
等 - 在内容组件中抛出特定事件支持关闭dialog
- 支持显示内容为
jsx
、普通文本
、Vue Component
- 支持在显示内容中控制是否可以关闭的回调函数,例如
beforeClose
- 支持显示之前钩子例如
onBeforeOpen
- 支持定义和弹出时修改配置属性
- 支持继承root vue的prototype,可以使用例如
vue-i18n
的$t
函数 - 支持
ts
参数提示
准备useDialog.ts
文件实现类型定义
1 | import type { Ref } from 'vue' |
接着实现普通useDialog
函数
下面函数我们实现了基础的用法,包括了:1,2,3,4,6,11 目标
1 | export function useDialog<P = any>(content: Content, options?: Ref<Options<P>> | Options<P>) { |
接下来我们实现目标5
- 需要在定义中支持
closeEventName
1 | interface Options<P> { |
- 修改
useDialog
函数接收closeEventName
事件关闭dialog
1 | export function useDialog<P = any>(content: Content, options?: Ref<Options<P>> | Options<P>) { |
接下来我们实现目标7
、8
- 需要在定义中支持
onBeforeOpen
,beforeCloseDialog
默认是传给内容组件,有组件调用设置
1 | type DialogProps = ElDialogInstance['$props'] & { |
- 修改
useDialog
函数接收onBeforeOpen
事件&传递beforeCloseDialog
1 | export function useDialog<P = any>(content: Content, options?: Ref<Options<P>> | Options<P>) { |
接下来我们实现目标9
、10
1 | // 定义工具函数,获取计算属性的option |
通过上面的封装,我们可以看到使用useDialog Hook之后,我们只需要在需要弹窗的地方引入这个Hook,然后调用openDialog方法即可,非常方便和简洁。
而且这样的封装还可以让我们在以后需要修改弹窗逻辑的时候更加方便,只需要在useDialog Hook中进行修改即可,不需要在各个地方进行重复的修改。
使用我们的useDialog
hook 解决我们上面的问题
创建components/buy.vue
购买组件
1 | <script lang="ts" setup> |
在pages/subscription.vue
页面中使用buy.vue
购买组件
1 | <script lang="ts" setup> |
在其他功能页面中弹出buy.vue
购买组件
1 | <script lang="ts" setup> |
其他useDialog hook的应用
beforeClose
& closeEventName
示例
buy.vue
购买组件
1 | <script lang="ts" setup> |
1 | <script lang="ts" setup> |
总结
通过使用useDialog Hook封装el-dialog,我们可以让前端技术变得更加有趣和简洁。希望大家也能尝试一下这样的封装方式,让我们的前端代码变得更加优雅和易维护。就像一位优秀的厨师一样,掌握了精妙的调味技巧,让每道菜都变得美味可口!