微信小程序开发小程序学习我爱编程

微信小程序之自定义dialog组件

2018-04-12  本文已影响306人  Benny_lzb

由于项目开发需求,坑爹的小程序没有自定义dialog(类似饿了么组件那种)。于是百度了下思路,开发了一个。

参数:
title  标题
cancelText  取消文本 (默认文本为取消)
confirmText  确认文本(默认文本为确定)
animated  是否动画 (默认为是)
modalSize  模态框大小(默认md)
animationOption  动画事件(默认300s)

接下来分享下实现步骤吧...主要的概念就是想把自定义的部分通过<slot>插槽来接收。

  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>
  1. 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哦~

上一篇下一篇

猜你喜欢

热点阅读