zoukankan      html  css  js  c++  java
  • 一个popup弹窗实现思路--(基于mintui分析)

    如何实现一个 messagebox/日期组建/popup

    常规实现思路

    - 新建一个messagebox组建...
    
    - 黑色遮罩封装在messagebox中
    
    - 黑色遮罩 加上样式
    
        {
            position: fixed:
            z-index: 999;
            opcity: .6
        }
        
    
    收工~
    

    这样有两个问题

    • 多个弹窗连续弹出的时候 遮罩层会叠加越来越深
    • 如果再有一个类似的其他弹窗(如第二幅图)还要再写一个遮罩,这个时候他们的层级高低容易出现问题

    解决方案:参考mintui 的popup实现方法

    对黑色弹窗做统一管理 popup-manager.js

    关键就再下面两个方法

    
    openModal: function(id, zIndex, dom, modalClass, modalFade) {
        if (Vue.prototype.$isServer) return;
        if (!id || zIndex === undefined) return;
        this.modalFade = modalFade;
    
        const modalStack = this.modalStack;
    
        for (let i = 0, j = modalStack.length; i < j; i++) {
          const item = modalStack[i];
          if (item.id === id) {
            return;
          }
        }
    
        const modalDom = getModal();
    
        addClass(modalDom, 'v-modal');
        if (this.modalFade && !hasModal) {
          addClass(modalDom, 'v-modal-enter');
        }
        if (modalClass) {
          let classArr = modalClass.trim().split(/s+/);
          classArr.forEach(item => addClass(modalDom, item));
        }
        setTimeout(() => {
          removeClass(modalDom, 'v-modal-enter');
        }, 200);
    
        if (dom && dom.parentNode && dom.parentNode.nodeType !== 11) {
          dom.parentNode.appendChild(modalDom);
        } else {
          document.body.appendChild(modalDom);
        }
    
        if (zIndex) {
          modalDom.style.zIndex = zIndex;
        }
        modalDom.style.display = '';
    
        this.modalStack.push({ id: id, zIndex: zIndex, modalClass: modalClass });
      },
    
      closeModal: function(id) {
        const modalStack = this.modalStack;
        const modalDom = getModal();
    
        if (modalStack.length > 0) {
          const topItem = modalStack[modalStack.length - 1];
          if (topItem.id === id) {
            if (topItem.modalClass) {
              let classArr = topItem.modalClass.trim().split(/s+/);
              classArr.forEach(item => removeClass(modalDom, item));
            }
    
            modalStack.pop();
            if (modalStack.length > 0) {
              modalDom.style.zIndex = modalStack[modalStack.length - 1].zIndex;
            }
          } else {
            for (let i = modalStack.length - 1; i >= 0; i--) {
              if (modalStack[i].id === id) {
                modalStack.splice(i, 1);
                break;
              }
            }
          }
        }
        
        ifIsNested(modalDom)
    
        if (modalStack.length === 0) {
          if (this.modalFade) {
            addClass(modalDom, 'v-modal-leave');
          }
          setTimeout(() => {
            if (modalStack.length === 0) {
              if (modalDom.parentNode) modalDom.parentNode.removeChild(modalDom);
              modalDom.style.display = 'none';
              PopupManager.modalDom = undefined;
            }
            removeClass(modalDom, 'v-modal-leave');
          }, 200);
        }
      }
    };
    
    

    modal --表示 黑色遮罩

    dom -- 表示 黑色遮罩上面的白色内容区域

    当打开弹窗的时候主要做两件事

    1 手动生成 modal 并添加到modalDom的父节点下 dom.parentNode.appendChild(modalDom);

    - modal 的每一个id 唯一
    - modal 的z-index 每当新生成一个都会自增
     - dom的z-index 每当新生成一个都会自增 且比modal的大一
    - appendChild 有一个重要的属性 如果文档树中已经存在了 newchild,它将从文档树中删除,然后重新插入它的新位置,这个有什么用呢,如下 
    
    
    <div id="c">
        <div id="a">
            <modal id="我是弹窗a">
            <zhezhao id="我是遮罩,当弹窗a出来的时候我会被插入到这个位置,我只会有一个">
        </div>
        
        <div id="b">
            <modal id="我是弹窗b">
            <zhezhao id="我是遮罩,当弹窗b出来的时候我会被插入到这个位置,我只会有一个">
        </div>
        
        <modal id="我是弹窗c">
        <zhezhao id="我是遮罩,当弹窗c出来的时候我会被插入到这个位置,我只会有一个">
    </div>
    
    如此便能不用手动removechild 同时保证只有一个遮罩,
    

    2 把生成的modal 添加到数组里

    当关闭弹窗的时候主要做一件事

    1 将遮罩的 z-index改成之前保存在数组里的上一个遮罩的index值

    如此基本可以满足大部分需求

    然而当 popup 嵌套modal的时候 原库会出现modal位置错误的问题

    解决方案也很简单在调用关闭方法的时候调用下面方法

    /**
     * 判断modalDom 是否是再其他 popup中嵌套,如果是嵌套则将modal 移动到最外层modal的父节点下面
     * @param {最后一次生成的modalDom} modalDom 
     */
    const ifIsNested = function(modalDom) {
      if (modalDom) {
        if (modalDom.parentNode && modalDom.parentNode !== document.body) {
          if (modalDom.parentNode.parentNode && modalDom.parentNode.parentNode.className && modalDom.parentNode.parentNode.className.indexOf('mint-popup') !== -1) {
            modalDom.parentNode.parentNode.parentNode.appendChild(modalDom)
          }  else {
            isNested(modalDom.parentNode)
          }
        }
      }
    }
    
    

    补充二

    想到一种弹窗组件 按照常规写法,调用的时候如果是要在业务组件里 通过 这样调用 而不是通过 this.$messagebox('')这样调用 会产生的问题

    这种情况是 当我们有如下页面

    
    <div class="left" style="z-index:100">
        我是聊天左侧
    </div>
    <div class="right  style="z-index:99">
        我是聊天右侧
        <messagebox>我是弹窗,无论给我设置多高的zindex 我都不会盖住左侧聊天框</messagebox
    </div>
    
    
  • 相关阅读:
    Sencha的Eclipse插件提示和技巧
    《敏捷软件开发过程及最佳实践》培训总结
    《Sencha应用程序的UI测试 》一文的示例分析
    Ext JS 4.2 Beta版发布
    迅速解决resin或者tomcat启动闪一下就消失的问题
    import javax.servlet 出错
    有爱好者把我的CMS管理系统改成了JAVA版,有兴趣的可以看看
    一个@符号引发的血案:Access数据库无法更新
    Windows 7下如何安装和配置IIS 7和ASP
    .Net中Freetextbox_1.6.3的使用与ftb.imagegallery.aspx安全修正
  • 原文地址:https://www.cnblogs.com/WhiteHorseIsNotHorse/p/9825521.html
Copyright © 2011-2022 走看看