操作组件的 promise 化

cpf23333大约 2 分钟

操作组件的 promise 化

有的时候一些业务里可能需要我们调用某个组件通过弹窗让用户选择或填入一些数据

但是否真的要让用户进行操作是不确定的,于是我们想当然的在每个页面里都去导入这个组件,用 v-if 只在需要时显示这个弹窗

这样在页面上是实现了,但判断是否需要选择的条件可能在操作里的某个接口里,然后需要获取选择数据的位置就在代码的下一行

可能会有人把后面的逻辑写成另一个函数,选择弹窗点击确定后收到选择的数据再去执行后面的函数

但这样每个页面都需要导入一个组件,再去监听一个事件,收到数据再去判断是否去执行后面的逻辑,这样太麻烦了,心智负担过重

可以考虑把这个弹窗封装成一个 promise,把业务处理函数改为 async 函数,哪里需要这个弹窗的结果,哪里 await 这个 promise 的结果就可以了

import Vue from "vue"
import i18n from "@/locale/index.js"
import store from "@/store/index.js"
import seelctDataDialog from "@/xxx/seelctDataDialog.vue"
export function promiseDialog() {
  let dialogComInstance
  let dom
  return new Promise((resolve, reject) => {
    let dialogCom = Vue.$extend({
      data() {
        return {}
      },
      created() {
        this.$nextTick(() => {
          this.$refs.dialog.visible = true
          // 监听弹窗组件的显隐,隐藏就意味着用户操作完毕
          this.$watch("$refs.dialog.visible", val => {
            if (val) {
              // 假定校验并取值的函数叫getVal
              this.$refs.dialog
                .getVal()
                .then(data => {
                  resolve(data)
                  // 操作有了一个结果,可以开始清除这个vue组件的实例和dom了
                  dialogComInstance.$destory()
                  dom.remove()
                  dom = null
                })
                .catch(err => {
                  reject(err)
                  dialogComInstance.$destory()
                  dom.remove()
                  dom = null
                })
                .finally(() => {
                  // dialogComInstance.$destory()
                  // dom.remove()
                  // dom = null
                  // 这三行在then和catch里各写一遍而不是在finally里写是因为getVal很可能是异步函数
                  // getVal执行所需的时间无法确定,就无法保证getVal和finally内同步或异步代码的执行顺序
                })
            }
          })
        })
      },
      render(h) {
        return <seelctDataDialog ref="dialog" />
      },
    })
    dialogComInstance = new dialogCom({ i18n, store })
    dom = dialogComInstance.$mount()
    document.body.appendChild(dom)
  })
}

使用

import { promiseDialog } from "@/utils"
export default {
  methods: {
    async toSubmit() {
      try {
        let form = await this.validate()
        if (form.xxx) {
          // 选择人员
          form.aaaa = await promiseDialog()
        }
        sendData(form)
          .then(res => {
            console.log("操作成功")
          })
          .catch(err => {})
      } catch (error) {}
    },
  },
}
上次编辑于:
贡献者: cpf23333