微信小程序 自定义封装模态框modal组件

小程序的设计没法用第三方框架包,而他自己也没有好用的模态框,只有几个基本弹出框,无法满足业务需求,所以决定自己封装一个模态框组件。

此组件设计了从上下左右四个方向弹出,目前只是测试版本:

微信小程序 自定义封装模态框modal组件_第1张图片

1.设计思路

传统的模态框就是有个div然后用平滑过渡动画使它弹出。

首先需要考虑动画的选择,由于小程序中js无法控制dom,也就无法控制css,所以用@frame的方式做动画不可取,因为无法给css中传值;

然后考虑到小程序自带的用js控制动画,结果里面全是坑,非常不好用,谁用是知道。

结果只能是用css中自带动画一条路了。

利用transiton和transform:translate解决平滑过渡问题

然后就是高度和模态框的位置可以通过参数控制了

新建出modal组件(新建component)

微信小程序 自定义封装模态框modal组件_第2张图片

2.代码实现

我尝试先粘代码再解释

modal.wxml:





  
   
    
    
  
  
  
    
  

因为小程序中想用js控制css只有在wxml中添加行内样式接收js参数一种方法,所以我把可变样式都用{{}}方式接收。

showModalStatus控制模态框是否显示,点击x号或者遮罩层模态框消失

这个x号按钮我用了fontawesome字体,由于组件中不能引用外部css,所以需要在引用modal的页面加上字体css,这个字体转css有些麻烦,可以直接用字母x代替他。

组件中一般都需要有slot,用于页面引用时添加自定义标签用的,我这里加了一个slot用于modal名字,一个slot用于modal内容,

多个slot用name区分

modal.xwss:

/*遮罩层*/
.mask{
  position: fixed;
  width:100%;height:100%;
  background:rgba(0,0,0,0.5);
  top:0;left:0;
  z-index: 10;transition: all 300ms ease-out;
}
/*弹出模态框*/
.mymodal{
  width:100%;
  position: fixed;z-index: 20;
  background:white;height:460px;
  border-radius: 10rpx;transition: all 300ms ease-out;
}
.mymodal .mymodal-title{
  font-size:30rpx;height:50px;line-height:50px;
  border-bottom:1px solid #ddd;
  color:#666;padding:0 20px;
  display: flex;justify-content:space-between;
  align-items: center
}
.mymodal .mymodal-content{
  padding:15px;height:320px;overflow: scroll;
}

css就是简单的样式,注意给modal和mask加个transition就行了,动画效果都是动态改变modal的top,left等值,有transition就会有平滑过渡效果

modal.js:

Component({
  /**
   * 组件的属性列表(共有数据)
   */
  properties: {
    //modal出现动画类型
    fadeStyle: {
      type: String,
      value: '',
      observer(newVal, oldVal, changedPath) {
      // 属性被改变时执行的函数(可选),通常 newVal 就是新设置的数据, oldVal 是旧数        
        if (newVal == "slideUp") {//从下向上滑出
          this.setData({
            bottom: '-' + this.properties.height,
          })
        } else if (newVal == "slideDown") {//从上向下滑出
          this.setData({
            top: '-' + this.properties.height,
          })
        } else if (newVal == "slideRight") {//从左向右滑出
          this.setData({
            left: '-' + this.properties.width
          })
        } else if (newVal == "slideLeft") {//从右向左滑出
          this.setData({
            right: '-' + this.properties.width
          })
        }
      }
    },
    width: {
      type: String,
      value: '100%',
    },
    height: {
      type: String,
      value: '',
    },
    top: {
      type: String,
      value: ''
    },
    bottom: {
      type: String,
      value: ''
    },
    left: {
      type: String,
      value: ''
    },
    right: {
      type: String,
      value: ''
    },
    opacity: {
      type: String,
      value: '0'
    },
  },

  /**
   * 组件的初始数据(私有数据)
   */
  data: {
    //控制模态框打开关闭参数
    showModalStatus: false
  },
  options: {
    addGlobalClass: true, //使其可以使用全局样式
    multipleSlots: true //使其可以使用多个slot,用name区分
  },
  /**
   * 组件的方法列表
   */
  methods: {
    //打开模态框
    showModal: function(event) {
      this.setData({
        showModalStatus: true
      })
      //需要等模态框出现再执行动画,否则无动画效果
      setTimeout(function() {
        if (this.properties.fadeStyle == "slideUp") {
          this.setData({
            bottom: 0,
            opacity: 1
          })
        } else if (this.properties.fadeStyle == "slideDown") {
          this.setData({
            top: 0,
            opacity: 1
          })
        } else if (this.properties.fadeStyle == "slideRight") {
          this.setData({
            left: 0,
            opacity: 1
          })
        } else if (this.properties.fadeStyle == "slideLeft") {
          this.setData({
            right: 0,
            opacity: 1
          })
        }

      }.bind(this), 100)
    },
    //关闭模态框
    closeModal: function() {
      //判断动画样式
      if (this.properties.fadeStyle == "slideUp") {
        this.setData({
          bottom: '-' + this.properties.height,
          opacity: 0
        })
      } else if (this.properties.fadeStyle == "slideDown") {
        this.setData({
          top: '-' + this.properties.height,
          opacity: 0
        })
      } else if (this.properties.fadeStyle == "slideRight") {
        this.setData({
          left: '-' + this.properties.width,
          opacity: 0
        })
      } else if (this.properties.fadeStyle == "slideLeft") {
        this.setData({
          right: '-' + this.properties.width,
          opacity: 0
        })
      }
      //等关闭动画完毕后再移除模态框和遮罩
      setTimeout(function() {        
        this.setData({
          showModalStatus: false
        })
      }.bind(this), 400)
    }
  }
})

组件component中有properties用于存放共有信息和data用于存放私有信息。由于模态框大小和位置采用可控制设计,所以在properties中设置模态框位置参数用于接收引用页面传来的参数。

fadeStyle为动画样式,通过observer监听fadeStyle的变化,判断不同的动画类型而采取不同的方式策略。

我这样设计width和height可以传px也可以传百分数。

然后执行弹出和关闭时都控制一下动画就行了。

值得一提的是当showModalStatus为true时,理论上模态框出现然后执行动画,但貌似modal的出现需要点时间,最好定时100ms后再执行动画,否则会出现动画不稳定

modal.json

{
  "component": true,
  "usingComponents": {}
}

作为一个组件,需要在json中写上component:true才行

3.页面引用

test.json

{
  "usingComponents": {
    "my-modal": "/assets/components/modal/modal"
  }
}

由于json文件比较重要,我放在前面

在需要引用组件的页面的json中,需要写上usingComponents,my-modal为自己起得名字,你起啥名字引用的时候就用啥名字,后面写上组件的路径即可 

test.wxml:




  这是个自定义模态框
  

my-modal就是json中自己起得名字

注意写上id,js中调用组件方法需要用到这个id寻找组件

然后就是我们自定义的参数,fadeStyle对应modal.js 中properties中的fadeStyle,要注意在这里设置的参数properties中都是可以接收到的,并且会触发oberver监听。width,height,top等都可以设置




  这是个自定义模态框
  



  这是个自定义模态框
  



  这是个自定义模态框
  

test.js

Page({
  data: {

  },
  onLoad: function (options) {
    this.modal = this.selectComponent("#modal");//通过给组件所起的id调用组件
  },
  showModal:function(){
    this.modal.showModal()  //调用组件中打开模态框方法
  }  
})

onload是用前面设置的id把组件调出来加到this中,注意只能是id

然后点击按钮时调用组件打开模态框方法即可

 

这只是个demo,实战中将自己的内容放到slot中,例如:


  这是个自定义模态框
  
    
      
      
      
    
    
      
        套餐名称
        资费,分钟,流量
        人气
      
      
        {{data.PACKAGE_NAME}}
        {{data.FEE}},{{data.DURATION}},{{data.FLOW}}
        {{data.POPU_VALUE}}
      
    
  

4.总结

犹豫刚学小程序,好多地方都考虑不周到,这里只是总结一下自己的思路,起码自己目前可以使用

提供个下载吧,不想看废话的可以直接下载看看效果

下载地址:https://download.csdn.net/download/lianzhang861/10980422

 

 

 

 

 

 

你可能感兴趣的:(小程序)