美文网首页
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