土鳖小屋

 找回密码
 欢迎注册

QQ登录

只需一步,快速开始

03广告位出售中
广告出售中
广告位
搜狗联盟招募 收益最高
亿恩免费建网站 服务器特价
【网维体】微信营销平台
【多线高防】无视一切攻击!广告
百度站长平台 精确提升SEO
21广告位高权重链接招租
大型装修门户助您抢占商机天翼云主机 四川资源池开启
国内/香港主机/试用/更有免费
微信小程序微信营销项目诚招代理
网游免费破解论坛
广告位 
查看: 92|回复: 0

[新手基础] 微信小程序之自定义dialog组件的实现方式

[复制链接]
弗罗多 发表于 2018-4-14 07:54 | 显示全部楼层 |阅读模式
阿里云学生主机9.9元
悦淘淘

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


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

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

1、创建好components组件且命好名字。 小tips:在微信开发工具内创建方便点它会自动帮你把相关文件配好。

创建组件且命名

2、写好相关布局及样式。

  1. dialog.wxss

  2. /** 模态 **/
  3. .modal{
  4.    position: fixed;
  5.    top: 0rpx;
  6.    left: 0rpx;
  7.    right: 0rpx;
  8.    bottom: 0rpx;
  9.    width: 100%;
  10.    height: 100%;
  11.    z-index: 100;
  12. }

  13. .modal-mask{
  14.    position: absolute;
  15.    width: 100%;
  16.    height: 100%;
  17.    z-index: 97;
  18.    background-color: rgba(0,0,0,0.30);
  19. }


  20. .modal-layer-sm{
  21.     width: 60%;
  22.     transform : translate3d(-50%,-50%,0);
  23.     left : 50%;
  24. }

  25. .modal-layer-md{
  26.     width: 80%;
  27.     transform : translate3d(-50%,-50%,0);
  28.     left : 50%;
  29. }

  30. .modal-layer-full{
  31.     width: 100%;
  32.     left: 0;
  33. }


  34. .modal-layer{
  35.    position: absolute;
  36.    background: transparent;
  37.    top: 50%;
  38.    display: flex;
  39.    flex-direction: column;
  40.    z-index: 98;
  41.    box-shadow: 0 4rpx 14rpx rgba(0,0,0,.4);
  42. }

  43. .modal-header{
  44.    background: #fff;
  45.    color: #333;
  46.    padding: 20rpx;
  47.    font-size: 30rpx;
  48.    text-align: center;
  49.    border-top-left-radius: 10rpx;
  50.    border-top-right-radius: 10rpx;
  51. }

  52. .modal-body{
  53.    flex: 1;
  54.    padding: 0 40px 40rpx;
  55.    background: #ffffff;  
  56. }



  57. .modal-footer{
  58.    background: #ffffff;
  59.    flex-direction: row;
  60.    display: flex;
  61.    align-items: center;
  62.    width: 100%;
  63.    border-top : 1rpx solid #eee;   
  64.    border-bottom-left-radius: 10rpx;
  65.    border-bottom-right-radius: 10rpx;
  66. }

  67. .modal-close{
  68.    color: #fff;
  69.    font-size: 48rpx;
  70.    position: absolute;
  71.    right: 40rpx;
  72.    top: 0;
  73.    z-index: 98;
  74. }


  75. .btn{
  76. flex: 1;
  77. text-align: center;
  78. font-size: 30rpx;
  79. color:#666;
  80. padding: 19rpx 5rpx;
  81. }
  82. .btn:first-child{
  83.    border-right: 1px solid #eee;
  84. }
  85. .btn-primary{
  86. color: #009887;   
  87. }


  88. dialog.wxml

  89. <view animation="{{animationData}}" hidden="{{!isShow}}" class='modal'>

  90. <view data-type="mask" catchtap='hideModal' class='modal-mask' ></view>

  91. <view class='modal-layer  modal-layer-radius {{modalSize == "sm" ? " modal-layer-sm" : " modal-layer-md" }} ' >

  92. <!-- 头部 -->
  93. <view class='modal-header'>
  94. <text>{{title}}</text>
  95. </view>

  96. <!-- 内容区域 -->
  97. <view class='modal-body'>
  98. <slot></slot>
  99. </view>
  100. <view class='modal-footer'>
  101. <text catchtap='_cancelModal' class='btn btn-default'>{{cancelText}}</text>
  102. <text catchtap='_confirmModal' class='btn btn-primary'>{{confirmText}}</text>
  103. </view>
  104. </view>
  105. </view>
  106. dialog.js
  107. // common/component/modal.js
  108. Component({   

  109.    /**
  110.     * 组件的属性列表
  111.     */
  112.    properties: {
  113.      title : {
  114.        type : String,
  115.        value : '这里是默认标题'
  116.      },

  117.      cancelText : {
  118.        type: String,
  119.        value: '取消'
  120.      },

  121.      confirmText : {
  122.        type: String,
  123.        value: '确定'
  124.      },

  125.      backdrop: {
  126.        type: Boolean,
  127.        value: true
  128.      },

  129.      animated : {
  130.        type: Boolean,
  131.        value: true
  132.      },

  133.      //模态框大小(sm md)
  134.      modalSize : {
  135.        type: String,
  136.        value: "md"
  137.      },

  138.      //动画时间(默认300)
  139.      animationOption : {
  140.        type : Object,
  141.        value  : {
  142.          duration : 300
  143.        }
  144.      },


  145.    },

  146.    /**
  147.     * 组件的初始数据
  148.     */
  149.    data: {
  150.      isShow:false,
  151.      animation : ''
  152.    },


  153.    ready: function () {   
  154.       this.animation = wx.createAnimation({
  155.          duration: this.data.animationOption.duration,
  156.          timingFunction: "linear",
  157.          delay: 0
  158.      });
  159.    },

  160.    /**
  161.     * 组件的方法列表
  162.     */
  163.    methods: {
  164.      //modal隐藏
  165.      hideModal : function(e){  
  166.        if(e){
  167.          let type = e.currentTarget.dataset.type;
  168.          if (type == 'mask' && !this.data.backdrop) {
  169.            return;
  170.          }   
  171.        }               
  172.        if (this.data.isShow) this._toggleModal();
  173.      },

  174.      //modal显示
  175.      showModal: function(){
  176.        if (!this.data.isShow) {
  177.          this._toggleModal();         
  178.        }
  179.      },

  180.      //切换modal的显示还是隐藏
  181.      _toggleModal:function(){      
  182.        if(!this.data.animated){
  183.            this.setData({
  184.              isShow: !this.data.isShow
  185.            })
  186.        }
  187.        else{
  188.          let isShow = !this.data.isShow;
  189.          this._executeAnimation(isShow);
  190.        }


  191.      },

  192.      //根据需求执行动画
  193.      _executeAnimation: function (isShow) {

  194.          let animation = this.animation;
  195.          if (isShow) {

  196.            animation.opacity(0).step();

  197.            this.setData({
  198.              animationData: animation.export(),
  199.              isShow: true
  200.            })

  201.            setTimeout(function () {
  202.              animation.opacity(1).step()
  203.              this.setData({
  204.                animationData: animation.export()
  205.              })
  206.            }.bind(this), 50)
  207.          }
  208.          else {
  209.            animation.opacity(0).step()
  210.            this.setData({
  211.              animationData: animation.export()
  212.            })

  213.            setTimeout(function () {
  214.              this.setData({
  215.                isShow: isShow
  216.              })
  217.            }.bind(this), this.data.animationOption.duration)

  218.          }


  219.        },
  220.        //取消事件 向外部page 发送事件通知
  221.        _cancelModal : function(){      
  222.          this.hideModal();     
  223.          this.triggerEvent("cancelEvent");
  224.        },

  225.        //确认事件
  226.        _confirmModal : function(){     
  227.          this.triggerEvent("confirmEvent");
  228.        }

  229.    }
  230. })
复制代码

核心都在这叻~注释都有哦。
分析下怎么做到自定义弹层吧。

slot图

通过slot图所示,从图中可以知道通过slot插槽来接受modal-body里头自定义的代码。因为这里只需要一个插槽,所以插槽的名字可以省略,会自动配上。如果是需要多个slot的话,记得为插槽加上name="xxx"属性命名哦,对应的视图块通过 slot="xxx"接受对应的插槽数据。


引用组件须知
  1. js部分
  2. 需用在页面渲染的时候获取组件

  3. onReady: function () {
  4. this.Modal = this.selectComponent("#modal");
  5. },


  6. 取消按钮以及确定按钮的回调事件

  7. _cancelEvent : function(){
  8.    console.log("点击取消!");
  9. }

  10. _confirmEventFirst : function(){
  11.    console.log("点击确定了!");
  12. this.Modal.hideModal();
  13. }


  14. 控制modal显示和隐藏

  15. this.Modal.showModal();//显示
  16. this.Modal.hideModal(); //隐藏
复制代码

对了。标题这块以及按钮块都可以根据自己的需求再做调整哦。
样式也可以调整。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?欢迎注册

x
    您需要登录后才可以回帖 登录 | 欢迎注册

    本版积分规则

    QQ|手机版|小黑屋|土鳖小屋 ( 豫ICP备14000521号-2  

    GMT+8, 2018-7-20 05:14

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表