实现popup公共弹窗

看到弹窗,给我的第一印象就是要找popup组件,其次是所在内容的组件。

基础

  • 基于vue编写公共popup组件

面临的问题

  • 显示隐藏
  • 弹窗位置
  • 渲染数据
  • 组件通信

解决思路

  1. 显示隐藏

    组件是放在全局的,既然是统一的公共组件,必然就要有统一的调用方法。

    • 首先想到的是统一规范约定的路由参数,通过监听参数变化控制popup的显示和隐藏以及数据的渲染。这种方式的弊端在于,参数加的莫名其妙,我们不需要去记录每一步的弹窗操作,如果在参数较多的情况下,会增加架构设计的复杂度,这种参数变化会显得多余。

      1
      url?popup=/popupType/:id
    • 第二种解决方案是通过vue组件之间的通信方式,在popup组件内通过bus.$on()监听其他组件通过bus.$emit()触发操作,触发时可以传入需要的参数,在监听的回调可以接收这个参数,然后就能根据参数去做其他事情了。这也是目前的处理方式。

      1
      2
      3
      4
      5
      6
      7
      8
      // import Vue from 'vue'
      const bus = new Vue()
      // 触发
      bus.$emit('popup-show', params)
      // 监听
      bus.$on('popup-show', callback)
      // 回收
      bus.$off('popup-show')
  2. 组件通信

    组件之间的通信也是通过vue实例对事件的监听和触发来完成的。这一步操作是在你编写的popup组件内部完成的。

  3. 渲染数据

    渲染数据是在组件内部完成的,在控制popup显示的时候可以传入需要查询数据的id或其他标识,然后在你编写的组件内部去做数据的渲染处理。

  4. 弹窗位置

    前面的几点都是基础,这一条才问题的关键。

    分析

    1. 触发popup显示的DOM元素和popup不在一个组件内。也就是说触发popup显示的DOM元素不是唯一的,可以是任意位置。
    2. 获取DOM元素在浏览器里的绝对位置和相对位置
    3. 获取popup组件的宽高
    4. 计算定位
    5. 监听resize,浏览器窗口大小改变时重新计算定位

抽象组件

  • 组件符合开闭原则,可扩展不可修改
  • 组件只负责数据,不包含任何业务逻辑