小程序模態(tài)框封裝
寫在前面
好久沒更新啦~~最近確實(shí)有點(diǎn)懶了,上完班都不想寫東西,小小檢討一下。最近在工作過程中涉及到了小程序的開發(fā)需求,在經(jīng)過一段時(shí)間的“艱苦奮斗”后,嘗試封裝了模態(tài)框組件,詳情如下:
基本使用
-
第一種方法:
- 在json文件中對組件進(jìn)行引用
"f-dialog": "/components/modelDialog/modelDialog"- 在全局對象中方法導(dǎo)入:
wx.fang.showDialog({ type:"alert", title:"標(biāo)題", content:"這個(gè)是提示框" , success: (res) => { if (res.confirm) { console.log('用戶點(diǎn)擊確定') } else if (res.cancel) { console.log('用戶點(diǎn)擊取消') } } })- 在使用的時(shí)候要在頁面上使用這個(gè)組件
<f-dialog></f-dialog> -
第二種方法
在json引入組件后直接寫入組件
<f-dialog showModel="{{showModel}}" type="confirm" title="你好" title-color="yellow" show-title="{{true}}" content="456789" content-color="blue" confirm-text="yes" confirm-color="red" cancel-text="no" cancel-color="blue" locked="{{true}}" bind:fangconfirm="onClickConfirm" bind:fangcancel="onClickCancel" ></f-dialog>
基本功能
| 屬性 | 功能 | 默認(rèn)值 |
|---|---|---|
| showModel | 是否顯示模態(tài)框 | true |
| title | 標(biāo)題內(nèi)容 | 標(biāo)題 |
| content | 主體內(nèi)容 | Dialog |
| confirmText | 確認(rèn)文字 | 確定 |
| confirmColor | 確認(rèn)文字顏色 | #48A0DC |
| cancelText | 取消文字 | 取消 |
| cancelColor | 取消文字顏色 | #000 |
| locked | 鎖定蒙版 | true |
| titleColor | 標(biāo)題顏色 | #000 |
| showTitle | 顯示標(biāo)題 | true |
| type | 模態(tài)框類型 | confirm/alert |
| contentColor | 主體內(nèi)容字體顏色 | rgba(89,108,142,1) |
外部樣式類
| 外部樣式類名 | 說明 |
|---|---|
| f-class | 設(shè)置dialog的整體樣式 |
| f-mask | 設(shè)置mask的樣式 |
| f-title | 設(shè)置標(biāo)題的樣式 |
| f-msg | 設(shè)置文本的樣式 |
| f-cancel-class | 設(shè)置取消按鈕的樣式 |
| f-confirm-class | 設(shè)置確認(rèn)按鈕的樣式 |
模態(tài)框事件
| 事件名稱 | 說明 | 返回值 |
|---|---|---|
| bind:fangConfirm | 當(dāng)點(diǎn)擊確定時(shí)觸發(fā)的事件 | confirm |
| bind:fangCancel | 當(dāng)點(diǎn)擊取消時(shí)觸發(fā)的事件 | cancel |
| bind:fangMask | 當(dāng)點(diǎn)擊模板的時(shí)候觸發(fā)的事件 | mask |
設(shè)置子節(jié)點(diǎn)
我們在使用的組件的時(shí)候,可以根據(jù)使用場景,自由的在遮罩層組件內(nèi)插入 image、 view、 text 等子節(jié)點(diǎn),當(dāng)然,你也可以在其中插入 自定義組件 。 (默認(rèn)會居中顯示在文本模塊)
例如:
<f-dialog>
<image class="abc" src="../xxx/xxx.png"></image>
</f-dialog>
源碼:
本著對大家負(fù)責(zé)的態(tài)度,上源碼交流學(xué)習(xí)
WXML
<!--components/modleDialog/modelDialog.wxml-->
<view class="dialog_container f-class " wx:if="{{isShow}}">
<!-- 蒙版 -->
<view
class="mask f-mask"
bindtap="clickMask"
data-status="{{locked}}"
catchtouchmove="move"
></view>
<view class="dialog_content" animation="{{animationData}}">
<view
class="dialog_content_title f-title"
style="color:{{titleColor}}"
wx:if="{{showTitle}}"
>{{title}}</view>
<view class="dialog_content_msg f-msg" style="color: {{contentColor}}">
<slot></slot>
{{content}}
</view>
<view class="dialog_content_btn">
<view
class="dialog_content_cancle f-cancel-class"
bindtap="onClickCancel"
style="color: {{cancelColor}}"
wx:if="{{judgeType}}"
>{{cancelText}}</view>
<view
class="dialog_content_confirm f-confirm-class"
bindtap="onClickConfirm"
style="color: {{confirmColor}}"
>{{confirmText}}</view>
</view>
</view>
</view>
JS
// components/modleDialog/modelDialog.js
Component({
/**
* 組件的屬性列表
*/
externalClasses: ['f-class', 'f-mask','f-title','f-msg','f-cancel-class','f-confirm-class'],
properties: {
showModel: {
type: Boolean,
value: true // 默認(rèn)打開彈窗
},
title: {
type: String,
value: '標(biāo)題'
},
content: {
type: String,
value: 'Dialog'
},
confirmText: {
type: String,
value: '確定'
},
confirmColor: {
type: String,
value: '#48A0DC'
},
cancelText: {
type: String,
value: '取消'
},
cancelColor: {
type: String,
value: '#000'
},
locked: {
type: Boolean,
value: true // 鎖定蒙版,點(diǎn)擊后無反應(yīng)
},
titleColor: {
type: String,
value: '#000'
},
showTitle: {
type: Boolean,
value: true
},
type: {
type: String,
value: 'confirm'
},
contentColor: {
type: String,
value: 'rgba(89,108,142,1)'
}
},
/**
* 組件的初始數(shù)據(jù)
*/
data: {
judgeType: true,
success: null,
fail: null
},
observers: {
'showModel': function(showModel) {
if (showModel) {
this._showOrCloseDialog("open")
} else {
this._showOrCloseDialog("close")
}
}
},
/**
* 組件的生命周期
*/
lifetimes:{
attached: function() {
if(this.properties.showModel) {
this._showOrCloseDialog("open")
}
this.initDialog()
// 在組件實(shí)例進(jìn)入頁面節(jié)點(diǎn)樹時(shí)執(zhí)行
if (this.data.type == 'alert') {
this.data.judgeType = false
this.setData({
judgeType: this.data.judgeType
})
} else if (this.data.type == 'confirm') {
this.data.judgeType = true
this.setData({
judgeType: this.data.judgeType
})
} else {
return
}
},
},
/**
* 組件的方法列表
*/
methods: {
initDialog() {
wx.fang = wx.fang || {}
wx.fang.showDialog = (options) => {
const {
type = 'alert',
title = '123',
showTitle = true,
titleColor= '#45526b',
content = '',
locked = true,
confirmText = '確定',
contentColor = 'rgba(89,108,142,1)',
cancelColor = '#45526b',
cancelText = '取消',
confirmColor = '#3683d6',
success = null,
fail = null,
} = options;
this.setData({
type,
title,
showTitle,
content,
titleColor,
locked,
confirmText,
cancelColor,
cancelText,
confirmColor,
contentColor,
showModel: true,
fail,
success
});
return this;
}
},
/**
* 點(diǎn)擊取消的事件
*/
onClickCancel(e) {
const {
success
} = this.data;
success && success({
confirm: false,
cancel: true,
errMsg: 'showDialog: success'
});
let detail = 'cancel'
this.triggerEvent('fangCancel',detail)
},
/***
* 點(diǎn)擊確定的事件
*/
onClickConfirm(e) {
const {
success
} = this.data;
let detail = 'confirm'
success && success({
confirm: true,
cancel: false,
errMsg: 'showDialog: success'
});
this.triggerEvent('fangConfirm',detail)
},
/**
* 點(diǎn)擊蒙版事件
*/
clickMask(e) {
let detail = 'mask'
if(!this.data.locked) {
this.data.showModel = false
this.setData({
showModel: this.data.showModel
})
}
this.triggerEvent('fangMask',detail)
},
/**
* 禁止背景滑動事件
*/
move() {},
/**
* 動畫函數(shù)
*/
_showOrCloseDialog: function(currentStatu) {
var that = this;
/* 動畫部分 */
var animation = wx.createAnimation({
duration: 200, //動畫時(shí)長
timingFunction: "linear", //線性
delay: 0 //0則不延遲
});
this.animation = animation;
// 執(zhí)行第一組動畫
animation.opacity(0).rotateX(-100).step();
// 導(dǎo)出動畫對象賦給數(shù)據(jù)對象儲存
that.setData({
animationData: animation.export()
})
// 設(shè)置定時(shí)器到指定時(shí)候后,執(zhí)行第二組動畫
setTimeout(function() {
// 執(zhí)行第二組動畫
animation.opacity(1).rotateX(0).step();
// 給數(shù)據(jù)對象儲存的第一組動畫,更替為執(zhí)行完第二組動畫的動畫對象
that.setData({
animationData: animation
})
//關(guān)閉
if (currentStatu == "close") {
that.setData({
isShow: false
});
}
}.bind(this), 200)
// 顯示
if (currentStatu == "open") {
that.setData({
isShow: true
});
}
}
}
})
WXSS
/* components/modleDialog/modelDialog.wxss */
.mask {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background:rgba(0,0,0,0.6);
z-index: 1000;
}
.dialog_content {
position: fixed;
top: 35%;
left: 50%;
margin-left: -275rpx;
display: flex;
flex-direction: column;
align-items: center;
width: 550rpx;
background-color: #fff;
z-index: 1999;
border-radius: 15rpx;
}
.dialog_content_title {
display: flex;
align-items: center;
justify-content: center;
height: 50rpx;
padding-top: 25rpx;
font-size: 35rpx;
font-weight: 700;
font-family:PingFangSC-Regular;
}
.dialog_content_msg {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
padding: 50rpx 10rpx 50rpx 10rpx;
overflow: hidden;
white-space: normal;
word-break: break-all;
font-family:PingFangSC-Regular;
}
.dialog_content_btn {
width: 100%;
height: 80rpx;
display: flex;
justify-content: space-between;
align-items: center;
border-top: 2rpx solid #ccc;
font-family:PingFangSC-Regular;
}
.dialog_content_cancle {
display: flex;
flex: 1;
align-items: center;
justify-content: center;
height: 100%;
border-bottom-left-radius: 15rpx;
}
.dialog_content_confirm {
height: 100%;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
color: #48A0DC;
border-left: 1rpx solid #e7e7e7;
border-bottom-right-radius: 15rpx;
}
小結(jié)
本次分享一個(gè)小程序的模態(tài)框封裝,具體可以參考vant組件庫,封裝過程有問題沒有解決:蒙版無法遮擋tabbar的問題,這也是歷史遺留問題了,我的方案是直接把tabbar隱藏掉,如果有更好的解決方案歡迎小伙伴提出。
Tip:本文寫得不是特別詳細(xì),適合有小程序基礎(chǔ)的小伙伴食用,有問題可在評論區(qū)提出哈~~~~
END