由于项目开发需求,坑爹的小程序没有自定义dialog(类似饿了么组件那种)。于是百度了下思路,开发了一个。
参数:
title 标题
cancelText 取消文本 (默认文本为取消)
confirmText 确认文本(默认文本为确定)
animated 是否动画 (默认为是)
modalSize 模态框大小(默认md)
animationOption 动画事件(默认300s)
接下来分享下实现步骤吧...主要的概念就是想把自定义的部分通过<slot>插槽来接收。
- 创建好components组件且命好名字。 小tips:在微信开发工具内创建方便点它会自动帮你把相关文件配好。
创建组件且命名 - 写好相关布局及样式。
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
对了。标题这块以及按钮块都可以根据自己的需求再做调整哦。
样式也可以调整。
附git地址https://github.com/jerryli519/dialogComponent。
路过的小伙伴给下star哦~
网友评论