美文网首页
Vue技巧之如何管理大量的对话框

Vue技巧之如何管理大量的对话框

作者: PeterQ1998 | 来源:发表于2018-10-30 11:24 被阅读0次

    前端比较忙的时候, 我这个后端也得帮忙改一下前端bug, 但是当我看的下面的代码时, 我的内心是崩溃的.

    vue页面组件, 注意代码行数

    这是公司内部用的管理后台, 一个vue组件1000多行, 看的我头大. 为啥这么大呢, 因为这个页面里面有很多对话框操作, 对话框里有交互逻辑, 甚至有网络请求. 因为有数据依赖前端把所有的弹框都写到一个页面里面了.并且打开,和关闭各个弹窗的逻辑是通过data对象里的变量控制的, 有多级弹框时非常的绕.


    控制弹框显示的变量

    我常用的一个技巧就是, 把弹框封装成一个组件, 并且写一个函数去使用, 该函数接受参数, 并返回一个Promise, 等弹框操作完成时, 调用弹窗的地方能拿到处理结果, 至于调用方,完全不用管弹窗内部逻辑如何实现, 甚至不用控制弹窗是否显示. 方便后期维护. 下面提供一种简单的实现方式
    DialogManager.js:

    
    import Vue from 'vue'
    
    // 对话框管理器
    const con = document.createElement('div')
    document.body.appendChild(con)
    
    // 复用组件实例
    const instances = []
    const comps = []
    
    // 对话框组件混入
    export const dialogMixin = {
      data: {
        visible: false,
        promise: null,
        param: {}
      },
      methods: {
        open(param) { // 由弹窗管理器调用
          this.visible = true
          this.param = param
          setTimeout(this.onOpen.bind(this, param))
          return new Promise((resolve, reject) => {
            this.promise = { resolve, reject }
          })
        },
        resolve(data) { // 弹窗交互成功
          this.visible = false
          this.$options.promise.resolve(data)
        },
        reject(reason) { // 弹窗交互失败
          this.visible = false
          this.$options.promise.reject(reason)
        },
        getPromise() { // 给父组件调用, 用来获取和弹窗绑定的Promise
          return this.$options.promise
        },
        onOpen(param) { // 弹窗组件通过这个方法接受父组件传过来的参数, 并进行初始化操作
          throw new Error('请实现onOpen方法')
        }
      }
    }
    
    // 打开一个对话框组件并返回这个实例
    export function openDialog(comp, param, recreate = true) {
      var ins
      // 构造Promise, 对话框操作完成销毁组件并移出dom
      const promise = new Promise((resolve, reject) => setTimeout(() => Object.assign(promise, { resolve, reject })))
        .finally(() => {
          if (recreate) {
            setTimeout(() => {
              con.removeChild(ins.$el)
              ins.$destroy()
            }, 1e3)
          }
        })
      if (!recreate && comps.indexOf(comp) > -1) {
        const ins = instances[comps.indexOf(comp)]
        ins.$options.promise = promise
        ins.open(param)
        return ins
      }
      // 强制混入
      comp.mixins = comp.mixins || []
      if (comp.mixins.indexOf(dialogMixin) < 0) {
        comp.mixins.push(dialogMixin)
      }
      // 构造实例插入容器, 并把这个Promise通过options传达给组件实例
      ins = new Vue({ promise, ...comp }).$mount()
      con.appendChild(ins.$el)
      ins.open(param)
      if (!recreate) {
        comps.push(comp)
        instances.push(ins)
      }
      return ins
    }
    

    定义一个弹框specialAction.vue, 此处省略
    ...

    在父组件中使用:

    import specialAction from './dialog/specialAction.vue'
    import { openDialog } from '@/utils'
    // 当某个按钮被点击时
    async openSpecialActionDialog(action, row) {
          await openDialog(specialAction, {
            action,
            bond: row
          }).getPromise()
          // 操作成功, 刷新债权列表
          await this.refreshBondList()
        }
    

    相关文章

      网友评论

          本文标题:Vue技巧之如何管理大量的对话框

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