由于项目开发需求,坑爹的小程序没有自定义dialog(类似饿了么组件那种)。于是百度了下思路,开发了一个。
title 标题 cancelText 取消文本 (默认文本为取消) confirmText 确认文本(默认文本为确定) animated 是否动画 (默认为是) modalSize 模态框大小(默认md) animationOption 动画事件(默认300s)
接下来分享下实现步骤吧...主要的概念就是想把自定义的部分通过插槽来接收。
1、创建好components组件且命好名字。 小tips:在微信开发工具内创建方便点它会自动帮你把相关文件配好。
创建组件且命名
2、写好相关布局及样式。
dialog.wxss
/** 模态 **/ .modal{ position: fixed; top: 0rpx; left: 0rpx; right: 0rpx; bottom: 0rpx; width: 100%; height: 100%; z-index: 100; } .modal-mask{ position: absolute; width: 100%; height: 100%; z-index: 97; background-color: rgba(0,0,0,0.30); } .modal-layer-sm{ width: 60%; transform : translate3d(-50%,-50%,0); left : 50%; } .modal-layer-md{ width: 80%; transform : translate3d(-50%,-50%,0); left : 50%; } .modal-layer-full{ width: 100%; left: 0; } .modal-layer{ position: absolute; background: transparent; top: 50%; display: flex; flex-direction: column; z-index: 98; box-shadow: 0 4rpx 14rpx rgba(0,0,0,.4); } .modal-header{ background: #fff; color: #333; padding: 20rpx; font-size: 30rpx; text-align: center; border-top-left-radius: 10rpx; border-top-right-radius: 10rpx; } .modal-body{ flex: 1; padding: 0 40px 40rpx; background: #ffffff; } .modal-footer{ background: #ffffff; flex-direction: row; display: flex; align-items: center; width: 100%; border-top : 1rpx solid #eee; border-bottom-left-radius: 10rpx; border-bottom-right-radius: 10rpx; } .modal-close{ color: #fff; font-size: 48rpx; position: absolute; right: 40rpx; top: 0; z-index: 98; } .btn{ flex: 1; text-align: center; font-size: 30rpx; color:#666; padding: 19rpx 5rpx; } .btn:first-child{ border-right: 1px solid #eee; } .btn-primary{ color: #009887; }
dialog.wxml
<view animation="{{animationData}}" hidden="{{!isShow}}" class='modal'> <view data-type="mask" catchtap='hideModal' class='modal-mask' ></view> <view class='modal-layer modal-layer-radius {{modalSize == "sm" ? " modal-layer-sm" : " modal-layer-md" }} ' > <!-- 头部 --> <view class='modal-header'> <text>{{title}}</text> </view> <!-- 内容区域 --> <view class='modal-body'> <slot></slot> </view> <view class='modal-footer'> <text catchtap='_cancelModal' class='btn btn-default'>{{cancelText}}</text> <text catchtap='_confirmModal' class='btn btn-primary'>{{confirmText}}</text> </view> </view> </view> dialog.js // common/component/modal.js Component({ /** * 组件的属性列表 */ properties: { title : { type : String, value : '这里是默认标题' }, cancelText : { type: String, value: '取消' }, confirmText : { type: String, value: '确定' }, backdrop: { type: Boolean, value: true }, animated : { type: Boolean, value: true }, //模态框大小(sm md) modalSize : { type: String, value: "md" }, //动画时间(默认300) animationOption : { type : Object, value : { duration : 300 } }, }, /** * 组件的初始数据 */ data: { isShow:false, animation : '' }, ready: function () { this.animation = wx.createAnimation({ duration: this.data.animationOption.duration, timingFunction: "linear", delay: 0 }); }, /** * 组件的方法列表 */ methods: { //modal隐藏 hideModal : function(e){ if(e){ let type = e.currentTarget.dataset.type; if (type == 'mask' && !this.data.backdrop) { return; } } if (this.data.isShow) this._toggleModal(); }, //modal显示 showModal: function(){ if (!this.data.isShow) { this._toggleModal(); } }, //切换modal的显示还是隐藏 _toggleModal:function(){ if(!this.data.animated){ this.setData({ isShow: !this.data.isShow }) } else{ let isShow = !this.data.isShow; this._executeAnimation(isShow); } }, //根据需求执行动画 _executeAnimation: function (isShow) { let animation = this.animation; if (isShow) { animation.opacity(0).step(); this.setData({ animationData: animation.export(), isShow: true }) setTimeout(function () { animation.opacity(1).step() this.setData({ animationData: animation.export() }) }.bind(this), 50) } else { animation.opacity(0).step() this.setData({ animationData: animation.export() }) setTimeout(function () { this.setData({ isShow: isShow }) }.bind(this), this.data.animationOption.duration) } }, //取消事件 向外部page 发送事件通知 _cancelModal : function(){ this.hideModal(); this.triggerEvent("cancelEvent"); }, //确认事件 _confirmModal : function(){ this.triggerEvent("confirmEvent"); } } })
核心都在这叻~注释都有哦。
分析下怎么做到自定义弹层吧。
slot图
通过slot图所示,从图中可以知道通过slot插槽来接受modal-body里头自定义的代码。因为这里只需要一个插槽,所以插槽的名字可以省略,会自动配上。如果是需要多个slot的话,记得为插槽加上name="xxx"属性命名哦,对应的视图块通过 slot="xxx"接受对应的插槽数据。
js部分
需用在页面渲染的时候获取组件
onReady: function () { this.Modal = this.selectComponent("#modal"); },
取消按钮以及确定按钮的回调事件
_cancelEvent : function(){ console.log("点击取消!"); } _confirmEventFirst : function(){ console.log("点击确定了!"); this.Modal.hideModal(); }
控制modal显示和隐藏
this.Modal.showModal();//显示 this.Modal.hideModal(); //隐藏
好了展示下效果呗~
效果图.png
对了。标题这块以及按钮块都可以根据自己的需求再做调整哦。
样式也可以调整。
路过的小伙伴给下star哦~