怎么封装一个更易用的Dialog组件
作者
怎么封装一个更易用的Dialog组件
这篇“怎么封装一个更易用的Dialog组件”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么封装一个更易用的Dialog组件”文章吧。
场景
在项目中,我们经常会遇到使用弹窗的场景,但有时组件库自带的弹窗不能满足我们的需求,需要我们自己封装,这时我们如何去自定义一个更加方便调用的弹窗?
搭建环境
首先我们需要搭建一个Vue3+ts的环境。
用vite的官方模板:
yarncreatevitedemo-app--templatevue-ts
进入并安装依赖
cddemo-appyarn
依赖安装完成后启动app
yarndev
创建组件
先在src/components目录下创建MyDialog.vue,搭建一个组件的基本框架
<scriptlang="ts"setup>import{ref,reactive}from"vue";defineProps({message:{type:String,default:"",},title:{type:String,default:"",},});constemits=defineEmits<{(e:"confirm"):void;(e:"close"):void;}>();constvisible=ref(true);functionclickConfirm(){console.log("确认");emits("confirm");}functionclickClose(){console.log("取消");emits("close");}</script><template><divclass="wrap"v-if="visible"><divclass="container"><divclass="title">{{title}}</div><divclass="content"><div>{{message}}</div></div><divclass="controll"><button@click="clickConfirm">确认</button><button@click="clickClose">取消</button></div></div></div></template><stylescoped>.wrap{position:absolute;top:0;left:0;background:rgba(15,15,15,0.5);width:100%;height:100%;}.container{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);min-width:300px;min-height:200px;padding:10px;background:white;display:flex;flex-direction:column;}.content{flex:1;padding:10px;text-align:left;}.title{min-height:30px;}.controll{display:flex;width:100%;justify-content:space-around;}</style>
创建调用组件的hook函数
在src目录下创建hooks目录,然后再hooks目录下创建useMyDialog.ts.
函数调用组件我们需要:
将组件转换成VNode
将VNode转换成DOM然后渲染到页面
import{createVNode,render,ComponentPublicInstance}from"vue";exportdefaultfunctionuseMyDialog(option?:any){constprops={...option,};constvm=createVNode(MyDialog,props);constcontainer=document.createElement("div");render(vm,container);document.querySelector("#app")?.appendChild(container.firstElementChild!);}
ps:
container.firstElementChild!中的!表示container.firstElementChild不为null或者undefined
接下来我们在App.vue中测试一下
<scriptsetuplang="ts">importuseMyDialogfrom"./hooks/useMyDialog";functionshowDialog(){useMyDialog({message:"test1",onClose:()=>{console.log("self");},});}</script><template><button@click="showDialog">显示Dialog</button></template>
Dialog的缓存、隐藏
隐藏
我们需要将close返回出去,这样我们就可以手动调用close函数关闭Dialog.
在useMyDialog.ts中添加
import{ComponentPublicInstance,VNode}from"vue";exportdefaultfunctionuseMyDialog(option?:any){constuserCloseFn=option?.onClose;props.onClose=()=>{close();userCloseFn??userCloseFn();};functionclose(vm:VNode){(vm.component!.proxyasComponentPublicInstance<{visible:boolean}>).visible=false;}return{close:close.bind(null,vm),}}
缓存
现在每次点击显示Dialog按钮时都会创建一个新的组件实例,这不是我们的预期,所以我们需要将组件进行缓存.
在useMyDialog.ts中添加
import{ComponentPublicInstance}from'vue'constinstances:any[]=[];exportdefaultfunctionuseMyDialog(option?:any){consttempVm:any=instances.find((item)=>`${item.vm.props?.message??""}`===`${(optionasany).message??""}`);if(tempVm){(tempVm.vm.component!.proxyasComponentPublicInstance<{visible:boolean;}>).visible=true;return{close:close.bind(null,tempVm.vm),};}}
完整代码
src/hooks/useMyDialog.ts
import{createVNode,render,ComponentPublicInstance,VNode}from"vue";importMyDialogfrom"../components/MyDialog.vue";constinstances:any[]=[];exportdefaultfunctionuseMyDialog(option?:any){constprops={...option,};constuserCloseFn=option?.onClose;props.onClose=()=>{close(vm);userCloseFn??userCloseFn();};functionclose(vm:VNode){(vm.component!.proxyasComponentPublicInstance<{visible:boolean}>).visible=false;}consttempVm:any=instances.find((item)=>`${item.vm.props?.message??""}`===`${(optionasany).message??""}`);if(tempVm){(tempVm.vm.component!.proxyasComponentPublicInstance<{visible:boolean;}>).visible=true;return{close:close.bind(null,tempVm.vm),};}constvm=createVNode(MyDialog,props);constcontainer=document.createElement("div");render(vm,container);document.querySelector("#app")?.appendChild(container.firstElementChild!);instances.push({vm});return{close:close.bind(null,vm),};}
以上就是关于“怎么封装一个更易用的Dialog组件”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注恰卡编程网行业资讯频道。
目录
推荐阅读
0 条评论
本站已关闭游客评论,请登录或者注册后再评论吧~