美文网首页小程序微信小程序
微信小程序组件化 快速实现可用模态窗

微信小程序组件化 快速实现可用模态窗

作者: 极乐叔 | 来源:发表于2017-12-06 15:38 被阅读0次

    纵观现代前端框架中(不论ng react vue ) 基本四架马车 声明式渲染 路由 组件化 状态管理。 反观小程序开发环境 缺失蛮多特性的 好在 11月初微信团队,发布了官方的component 化方案, 我们基本上可以告别现有的hack办法去实现 component 化。

    hack方式

    使用template实现组件化https://zhuanlan.zhihu.com/p/...

    使用include组件化
    这个简单说下 include 组件wxml 和样式文件到 page 然后 ,import 组件的js文件 通过合并方式将组件data method 合并到page 对于data,直接采用 Object.assign method 进行融合,先调用组件事件,然后调用父页面事件.

    以上方案核心: 将组件内定义的 data 和 method 合并到page中去 实现组件化, 本质上都在同一个作用域下组件作用域没有隔离,难免会出现 命名冲突 覆盖.

    实现一个组件

    方便快速理解,下面使用官方组件化方案 实现一个模态弹窗 easyModal.

    请结合源码看https://gitee.com/sherlock221...

    阅读前 请先读通官方自定义组件文档https://mp.weixin.qq.com/debu...

    组件分析

    首先分成2个小组件 来实现这个模态弹窗
    基本模态弹窗 和 增强型模态弹窗

    基本模态弹窗 具备

    1.显示/隐藏

    2.backdrop

    3.过度动画

    4.自定义头尾

    这几部分基础功能

    增强型模态弹窗 具备

    1.基础模态弹窗功能
    2.自定义内容区域
    3.title自定义
    4.确定取消按钮自定义

    基本模态窗

    首先在base文件夹下直接右键创建component -> baseModal
    在baseModal.js中创建组件所需要props 这些属性来自父组件或 外层page 中的数据,

    Component({    
    
      options : {
        multipleSlots: true 
      },
      /**
       * 组件的属性列表
       */
      properties: {
    
        backdrop: {
          type: Boolean,
          value: true
        },
    
        animated : {
          type: Boolean,
          value: true
        },
    
        modalSize : {
          type: String,
          value: "md"
        },
    
        animationOption : {
          type : Object,
          value  : {
            duration : 300 
          }
        }
    
      },
    }
    
    

    下来创建 data,isShow控制 弹窗显示和隐藏 animation则是弹窗动画函数.

    /**
       * 组件的初始数据
       */
      data: {
        isShow : false,
        animation : ''
      },
    
    

    在生命周期函数 ready中初始化animation

    ready: function () {   
         this.animation = wx.createAnimation({
           duration: this.data.animationOption.duration,
          timingFunction: "linear",
          delay: 0
        }); 
      },
    
    

    组件有2个public方法 show hide 方法, private 有执行动画 和 切换显隐的方法

    methods: {
          hideModal : function(e){  
            if(e){
              let type = e.currentTarget.dataset.type;
              if (type == 'mask' && !this.data.backdrop) {
                return;
              }   
            }                
            if (this.data.isShow) this._toggleModal();
          },
    
          showModal : function(){
            if (!this.data.isShow) {
              this._toggleModal();         
            }
          },
    
          _toggleModal : function(){      
            if(!this.data.animated){
                this.setData({
                  isShow: !this.data.isShow
                })
            }
            else{
              let isShow = !this.data.isShow;
              this._executeAnimation(isShow);
            }
    
          },
    
          _executeAnimation: function (isShow) {
            ......
          }
    
      }
    
    

    可以通过animated属性来判断 组件是否需要调用_executeAnimation 来执行动画显示

    页面结构

    <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'>        
                  <slot name="header">slot>             
              view>
    
              <view class='modal-body'>         
                   <slot name="body">slot>                          
              view>
    
              <view class='modal-footer'>
                   <slot name="footer">slot>                     
              view>
          view>
      view>
    
    

    slot 节点,用于承载组件使用者提供的wxml结构。
    默认情况下,一个组件的wxml中只能有一个slot。需要使用多slot时,记得开启配置

    options : {
        multipleSlots: true 
      },
    
    

    下来创建样式wxss
    具体可以看github 文件这就不贴

    /** 模态 **/
    .modal{
      position: fixed;
      top: 0rpx;
      left: 0rpx;
      right: 0rpx;
      bottom: 0rpx;
      width: 100%;
      height: 100%; 
      z-index: 100;
    }
    ..............
    
    

    需要注意 组件wxss文件 具备

    隔离性的

    你在page 中定义的class , 在app.wxss 中定义的class 都无法再组件中使用,如果真有一些需要复用到的样式 可以抽取成一个wxss 通过import 导入 组件的wxss

    @import "../../style/font.wxss";
    
    

    这样会增加组件和业务的耦合度 公共组件不建议使用

    接下来可以在业务界面中去使用

    <base-modal id="thridModal">
      <view slot="header" class='modal-header'>
            头部
        view>
         <view slot="body" class='modal-body'>
            中间
        view>
    
        <view slot="footer" class='modal-footer'>
             尾部      
        view>
    
    base-modal>
    
    

    别忘了在业务页面的json中引入组件

    { 
        "usingComponents": {     
          "base-modal": "/component/easyModal/base/baseModal"
        }
    
    }
    
    

    还记得我们上面baseModal 有两个public方法 怎么样去调用呢 这里介绍下

    Component 的一个实例方法 selectComponent
    通过它 可以找到子组件实例 这个有点像是 jq 选择器 通过selector去寻找dom(但是不是dom是js对象) 不过它更像是 react 或 vue ref this.$ [http://

    refs.xxx](http://link.zhihu.com/?target=http%3A//refs.xxx)

    获得组件实例.

    我们给这个组件创建一个id 通过id选择器就可以找到base-modal的实例 在ready中找到modal实例

    onReady: function () {     
        this.thridModal = this.selectComponent("#thridModal");
      },
    
    

    然后就可以调用实例的public的方法.

    this.thridModal.showModal();
    this.thridModal.hideModal();
    
    

    增强模态窗

    增强模态窗是基于baseModal的.

    {
      "component": true,
      "usingComponents": {
        "base-modal" : "../base/baseModal"
      }
    }
    
    

    注意 增强模态窗口 需要包含 基本模态窗口 json中引用才能使用

    <base-modal id="baseModal"   modalSize="{{modalSize}}"  animated="{{animated}}"  backdrop="{{backdrop}}">
        <view slot="header" class='modal-header'>
            <text>{{title}}text>
        view>
    
         <view slot="body" class='modal-body'>
            <slot>slot>
        view>
    
        <view slot="footer" class='modal-footer'>
             <text catchtap='_cancelModal' class='btn btn-default'>{{cancelText}}text>
             <text catchtap='_confirmModal'  class='btn btn-primary'>{{confirmText}}text>      
        view>
    
    base-modal>
    
    

    说下event部分 确定 取消按钮是需要 向外部page 发送事件通知的其进行业务操作的

    //cancel
        _cancelModal : function(){      
          this.hide();     
          this.triggerEvent("cancelEvent");
        },
    
        //success
        _confirmModal : function(){     
          this.triggerEvent("confirmEvent");
        }
    
    

    通过triggerEvent触发事件 这点和官网文档没有区别.

    业务Page界面:

    <easy-modal  
          id="easyModal" 
          title="这个是标题 01"   
          bind:cancelEvent="_cancelEvent"  
          bind:confirmEvent="_confirmEventFirst"  
          >  <view class='modal-content'>
                 <text> 这是内容部分 01 </text>     
                 <text> 这是内容部分 01 </text>     
                 <text> 这是内容部分 01 </text>                                             
          </view>    
    
    </easy-modal>
    
    

    一个基本模态窗口 就完成了, 满足基本业务使用 还有很多地方可以根据你们自身业务 进行 扩展.

    本文作者:sherlock221
    原文地址:微信小程序组件化 快速实现可用模态窗

    相关文章

      网友评论

        本文标题:微信小程序组件化 快速实现可用模态窗

        本文链接:https://www.haomeiwen.com/subject/csxlixtx.html