小程序模態(tài)框封裝

小程序模態(tài)框封裝

寫在前面

好久沒更新啦~~最近確實(shí)有點(diǎn)懶了,上完班都不想寫東西,小小檢討一下。最近在工作過程中涉及到了小程序的開發(fā)需求,在經(jīng)過一段時(shí)間的“艱苦奮斗”后,嘗試封裝了模態(tài)框組件,詳情如下:

基本使用

  1. 第一種方法:

    • 在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>
    
  2. 第二種方法

    在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)插入 imageview、 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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容