美文网首页让前端飞JS插件封装
手把手教你用原生Javascript封装一个Dialog组件

手把手教你用原生Javascript封装一个Dialog组件

作者: 聪明的汤姆 | 来源:发表于2018-08-10 14:27 被阅读0次

    分析

    对外暴露的方法

    • show(options) 显示dialog
      • options 参数
        • title 标题,默认为“”,不显示标题
        • content 主内容,默认为"兄弟,你好像忘记传content的值了"
        • skin 皮肤,默认为"",其实就是给dialog添加一个你的类名,方便重置样式
        • btns 按钮组,默认为['确认'],可选['xx',‘xx’],只取前两个作为有效值,第一个为confirm,第二个为cancel
        • confirm 点击confirm按钮的回调,如确认
        • cancel 点击cancel按钮的回调,如取消
        • shadeClose 是否开启点击遮罩关闭,默认true
        • animation 过渡动画,默认为1,可选0和2,注意这里的动画是指内容区的动画,最外层是固定为0
    • hide() 关闭dialog

    过渡动画
    用css3的animation,具体看下面的css

    先写好布局、样式(后面会移植到Javascript生成DOM)

    html

    <!-- 最外层 -->
    <div class="dialog-wrapper">
      <!-- 居中主要层 -->
      <div class="dialog">
        <!-- 标题 -->
        <div class="title">消息提示</div>
        <!-- 主要内容 -->
        <div class="content">兄弟,你好像忘记传content的值了</div>
        <!-- 按钮组 -->
        <div class="buttons">
          <div class="btn cancel-btn">取消</div>
          <div class="btn confirm-btn">确认</div>
        </div>
      </div>
    </div>
    

    css(可先跳过)

    body,
    html {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
    }
    
    .dialog-wrapper {
      position: fixed;
      display: flex;
      justify-content: center;
      align-items: center;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vh;
      background-color: rgba(49, 49, 49, 0.5);
      color: #313131;
      font-size: 10px;
      -webkit-tap-highlight-color: transparent;
    }
    
    .dialog-wrapper.fadeIn {
      animation: fadeIn .2s ease;
    }
    
    .dialog-wrapper.fadeOut {
      animation: fadeOut .2s ease forwards;
    }
    
    .dialog-wrapper .dialog {
      position: relative;
      width: 85vw;
      max-width: 30em;
      border-radius: .4em;
      background-color: #fff;
      box-sizing: border-box;
      overflow: hidden;
      box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.1);
    }
    
    .dialog-wrapper .dialog.slideDown {
      animation: slideDown .2s ease;
    }
    
    .dialog-wrapper .dialog.slideUp {
      animation: slideUp .2s ease forwards;
    }
    
    .dialog-wrapper .dialog.scaleIn {
      animation: scaleIn 0.2s cubic-bezier(0.07, 0.89, 0.95, 1.4);
    }
    
    .dialog-wrapper .dialog.scaleOut {
      animation: scaleOut 0.2s cubic-bezier(0.07, 0.89, 0.95, 1.4) forwards;
    }
    
    .dialog-wrapper .dialog .btn {
      cursor: pointer;
    }
    
    .dialog-wrapper .dialog .btn:active {
      background-color: #f4f4f4;
    }
    
    .dialog-wrapper .dialog .close-btn {
      position: absolute;
      top: 0;
      right: 0;
      padding: 10px;
      font-size: 1.8em;
    }
    
    .dialog-wrapper .dialog .title {
      font-size: 1.8em;
      padding: 15px;
      text-align: center;
      background-color: #f4f4f4;
    }
    
    .dialog-wrapper .dialog .title:empty {
      display: none;
    }
    
    .dialog-wrapper .dialog .content {
      padding: 40px 20px;
      font-size: 1.6em;
      text-align: center;
    }
    
    .dialog-wrapper .dialog .buttons {
      font-size: 1.6em;
      display: flex;
      flex-flow: row-reverse;
    }
    
    .dialog-wrapper .dialog .buttons .btn {
      flex: 1;
      padding: 15px;
      text-align: center;
      border-top: 1px solid #ebebeb;
    }
    
    .dialog-wrapper .dialog .buttons .btn.confirm-btn {
      color: #f2d985;
    }
    
    .dialog-wrapper .dialog .buttons .btn.cancel-btn {
      color: #313131;
      border-right: 1px solid #ebebeb;
    }
    
    @keyframes slideDown {
      from {
        transform: translateY(-3em);
      }
      to {
        transform: translateY(0);
      }
    }
    
    @keyframes slideUp {
      from {
        transform: translateY(0);
      }
      to {
        transform: translateY(-3em);
      }
    }
    
    @keyframes fadeIn {
      from {
        opacity: .5;
      }
      to {
        opacity: 1;
      }
    }
    
    @keyframes fadeOut {
      from {
        opacity: 1;
      }
      to {
        opacity: 0;
      }
    }
    
    @keyframes scaleIn {
      from {
        transform: scale(0.8);
      }
      to {
        transform: scale(1);
      }
    }
    
    @keyframes scaleOut {
      from {
        transform: scale(1);
      }
      to {
        transform: scale(0.8);
      }
    }
    

    Javascript封装

    第一步,基本搭建
    使用立即执行函数,只对外暴露两个方法,show和hide

    let dialog = (function () {
    
      // 节点类型
      let elem, dialog, cancelBtn, confirmBtn;
    
      // 动画函数数组
      let animaArr = new Array(['fadeIn', 'fadeOut'], ['slideDown', 'slideUp'], ['scaleIn', 'scaleOut']);
    
      // 当前动画类型
      let currAnimation = '';
    
      /**
       * @method getNeedElement 获取所需要的节点
       */
      let getNeedElement = function () {
    
      }
    
      /**
       * @method show 显示dialog组件
       * @param {Object} options 一系列参数
       * @returns {Object} 当前dialog节点
       */
      let show = function (options) {
    
      }
    
      /**
       * @method hide 关闭dialog组件
       */
      let hide = function (index) {
    
      }
    
      /**
       * @method bindEvent 给dialog绑定事件
       * @param {Object} confirm 确认回调
       * @param {Object} cancel 取消回调
       */
      let bindEvent = function (confirm, cancel, shadeClose) {
    
      }
    
      return {
        show,
        hide
      }
    
    })();
    

    第二步,编写show方法

    let show = function (options = {}) {
    
      // 默认参数
      let {
        title = '', content = '兄弟,你好像忘记传content值了',
          skin = '', btns = ['确定'],
          confirm = null,
          cancel = null,
          shadeClose = true,
          animation = 1
      } = options;
    
      // 皮肤类名
      let skinClass = skin ? ` ${skin}` : '';
    
      // 给当前动画类型赋值
      currAnimation = animation;
    
      // 生成按钮
      let btnTemp = '';
      btns.forEach((item, index) => {
        if (index == 2) return;
        let btnClass = index == 0 ? 'confirm-btn' : 'cancel-btn';
        let temp = `<div class="btn ${btnClass}">${item}</div>`
        btnTemp += temp
      })
    
      // 最终生成的HTML
      let html = `
        <div class="dialog-wrapper fadeIn">
          <div class="dialog${skinClass} ${animaArr[currAnimation][0]}">
            <div class="title">${title}</div>
            <div class="content">${content}</div>
            <div class="buttons">${btnTemp}</div>
          </div>
        </div>
      `;
    
      // 添加到Body
      document.body.innerHTML += html;
      // 获取所需要的节点
      getNeedElement();
      // 绑定事件
      bindEvent(confirm, cancel, shadeClose);
      return elem;
    
    }
    

    第三步,编写hide方法

    // 最外层加类名hide
    let hide = function () {
    
      // 最外层执行显示动画(固定)
      elem.classList.add('fadeOut');
      // 内容层执行关闭动画
      dialog.classList.add(`${animaArr[currAnimation][1]}`);
      // 最终移除
      setTimeout(() => {
        elem.remove();
      }, 200);
    
    }
    

    第四步,编写bindEvent方法

    let bindEvent = function (confirm, cancel) {
    
     // confirm按钮的回调
      confirmBtn && confirmBtn.addEventListener('click', e => {
        hide();
        confirm && confirm();
      })
    
      // cancel按钮的回调
      cancelBtn && cancelBtn.addEventListener('click', e => {
        hide();
        cancel && confirm();
      })
    
      // 是否开启点击遮罩关闭
      if (shadeClose) {
        elem.addEventListener('click', e => {
          let target = e.target || e.srcElement;
          if (/dialog-wrapper/.test(target.className)) {
            hide();
          }
        })
      }
    
    }
    

    第五步,编写getNeedElement方法

    let getNeedElement = function () {
      
      // 一家人最重要是整整齐齐
      elem = document.querySelector('.dialog-wrapper');
      dialog = elem.querySelector('.dialog');
      cancelBtn = elem.querySelector('.cancel-btn');
      confirmBtn = elem.querySelector('.confirm-btn');
    
    }
    

    调用以及效果图

    1. 无标题


    dialog.show({
      content: '抱歉,该游戏暂无Android版本'
    })
    
    1. 自定义标题和按钮


    dialog.show({
      title: '版本更新',
      content: '检测到最新版本为V1.0.2,是否更新',
      btns: ['立即更新', '暂不更新']
    })
    
    1. 动画效果为2时(弹性放大)


     dialog.show({
      title: '消息提示',
      content: '此操作将不可逆转,确定删除此项?',
      btns: ['确定', '怕了'],
      animation: 2
    })
    

    说明

    自己可以扩展更多自定义参数,动画需配合css3的animation

    如果您喜欢这篇文章,那么记得动动你们的👋,给个like或者关注我哦👍。

    相关文章

      网友评论

        本文标题:手把手教你用原生Javascript封装一个Dialog组件

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