当前位置: 首页 > Web前端 > vue.js

Vue3优雅模态框封装方法-实践

时间:2023-04-01 00:02:50 vue.js

my-blog:https://tuimao233.gitee.io/ma...Vue3优雅模态框封装方法-初探Vue3优雅模态框封装方法-实践通过介绍上一篇文章,你已经了解了虚拟节点和传送组件。接下来,我们使用虚拟节点和传送组件来封装一个模态框组件。首先我们要先明确我们的目标,也就是我们要做出的效果,兼容两种方式调用的模态框组件。第一种是直接通过模板使用:我是模态框的文字第二种是直接从JavaScript调用:Modal({title:'Title',content:'我是模态框的文字'}).then(()=>{}).catch(()=>{})从这两段可以看出,无论是通过Modal还是通过..,都可以传入的参数都是一致的。可以看出调用组件的方法是一致的,所以我们先创建components/Modal/props.ts,并在外部定义props参数类型:/**固定模态框的props参数,用于调用Modal框成功|close|destroy*/exportconstmodalProps={//是否显示组件modelValue:Boolean,//当组件消失时(移除实例)vanish:Function,//组件调用成功事件resolve:Function,//组件调用failureeventreject:Function}/**组件中传入的props参数用于模态框的自定义功能*/exportconstcomponentProps={//模态框的标题title:String,//模态框的内容box:String}/**组件中的所有Props参数,组合参数*/exportconstprops={...modalProps,...componentProps}这一步完成后,我们创建components/Modal/index.vue并导入道具类型:经过这一步,我们定义了一个通过js代码渲染组件的方法://components/Modal/utils.vueimport{Component,h,render}from"vue"/***Render组件实例*@paramConstructor组件*@paramprops组件参数*@returns组件Instance*/exportconstrenderInstance=(Constructor:Component,props:Record)=>{//创建组件容器,这一步是必须的,销毁时会用到const容器component=document.createElement('div')//在props中添加组件消失钩子,移除当前实例,为组件提供destroy方法//不需要调用document.body.removeChild(container.firstElementChild)//因为调用了render(null,container)这是为我们完成的props.vanish=()=>{render(null,container)}//创建虚拟节点,渲染组件entconstvnode=h(Constructor,props)render(vnode,container)//给父元素添加子元素(组件)document.body.appendChild(container.firstElementChild)}渲染方法定义好后,我们可以先制作js调用的方法:import{ExtractPropTypes,ref}from"vue"importIndexfrom'./index.vue'import{componentProps}from'./props'import{renderInstance}from"./utils"/**组件Props类型,ExtractPropTypes可以将Constructor转换成对应的值类型*/typeProps=ExtractPropTypes/**组件调用resolve返回结果*/typeResult={path:string}[]/***模态框调用方法*@paramprops*@returns{Promise}*/exportconstModal=(props:Props)=>{returnnewPromise((resolve,reject)=>{renderInstance(Index,{//这里是modelValue,为了让组件可以修改,需要传入ref//Pay注意这个地方,我们把这个值设置为true是为了直接显示组件modelValue:ref(true),...props,resolve,reject})})}这里要注意的是创建的实例的props通过h函数都在component中,不能通过emit修改,修改会失效,所以为了解决这个问题,需要在调用方法中传入modelValueRef接下来完善components/Modal/index.vue组件的模态框逻辑:任何)-->{{title}}

{{content}}确定关闭
.base-model__mask{位置:固定的;左:0;顶部:0;宽度:100%;高度:100%;背景色:rgba(0,0,0,0.4);}.base-model__content{position:absolute;20px;宽度:600px;高度:300px;背景色:#ffffff;顶部:50%;左:50%;转换:翻译(-50%,-50%);填充:20px;}.base-model__control{位置:绝对;右:0;底部:20px;span{margin-right:20px;}}/*组件动画开始*/.fade-enter-active,.fade-leave-active{transition:opacity0.2s;}.fade-enter-from,.fade-leave-to{opacity:0;}.fade-enter-top,.fade-leave-from{opacity:1;}/*组件动画结束*/到了这里,我们可以测试组件调用是否正常。比如我们使用模板组件来调用它:测试一下,通过JavaScript调用模态框框:至此,整个模态框的基本逻辑就形成了。在此基础上,可以根据需求内容对模态框进行改进和定制,也可以使用该方法重新封装el-dialog组件,只需com修改ponents/Modal/index.vue的逻辑即可。下一篇我们会在此基础上进行改进,让组件充分满足业务需求