【缤纷多彩】通过js实现对vue组件调用

193 阅读1分钟

如下图所示,在开发项目时经常遇到需要消息弹窗、确认弹窗等功能的业务,此类组件通常都是通过js调用,然而有时我们需要实现具有特定UI风格的此类组件,但有时对原有组件修改较为繁琐,往往会选择自行封装符合要求的组件。为了使用的便捷性,又想实现自定义组件可以像第三方组件一样实现通过js进行调用,那该如何做呢?下面让我们简单研究一下吧。

image.png

第一步,使用vue+antdesign实现一个二次确认组件Confirm.vue,如下:

<!--    二次确认弹窗    -->
<template>
  <a-modal
    :visible="visible"
    :closable="false"
    centered
    :title="title"
    :width="width"
  >
    <!--  弹窗body  -->
    <slot>
      <div v-html="content"></div>
    </slot>
    <!--  弹窗footer  -->
    <template slot="footer">
      <a-button v-if="sureBtnText" type="primary" @click="ok">
        {{ sureBtnText }}
      </a-button>
      <a-button v-if="cancelBtnText" type="default" @click="cancel">
        {{ cancelBtnText }}
      </a-button>
    </template>
  </a-modal>
</template>

<script>
import { Modal } from 'ant-design-vue'
export default {
  name: 'Confirm',
  props: {
    ...Modal.props,
    visible: {
      type: Boolean,
      default: false
    },
    width: {
      type: [String, Number],
      default: '480px'
    },
    title: {
      type: String,
      default: '系统提示'
    },
    sureBtnText: {
      type: String,
      default: '确定'
    },
    cancelBtnText: {
      type: String,
      default: '取消'
    },
    content: {
      type: String,
      default: '提示内容'
    }
  },
  model: {
    prop: 'visible',
    event: 'cancel'
  },
  data() {
    return {}
  },
  methods: {
    show() {
      this.visible = true
    },
    // 确定
    ok() {
      this.$emit('ok', false)
    },
    // 取消
    cancel() {
      this.$emit('cancel', false)
    }
  }
}
</script>

<style lang="scss" scoped>
::v-deep {
  .ant-modal-wrap {
    z-index: 9999;
  }
  .ant-modal-content {
    box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.15);
  }
  .ant-modal-header {
    border-color: #f5f5f5;
    padding: 32px 32px 12px 32px;
    border-bottom: none;
    .ant-modal-title {
      height: 24px;
      line-height: 24px;
      font-size: 16px;
      color: #333;
      font-weight: $font-medium;
    }
  }
  .ant-modal-body {
    padding: 0 32px 24px 32px;
    font-weight: 400;
    font-size: 14px;
    color: #666;
    line-height: 22px;
  }
  .ant-modal-footer {
    text-align: center;
    border-top: none;
    padding: 0;
    padding-bottom: 24px;
    overflow: hidden;

    .ant-btn {
      margin-right: 12px;
      margin-left: 0;
      &:last-of-type {
        margin-right: 0;
      }
    }
  }
}
</style>

第二步,使用vue构造器将Confirm.vue封装成可通过js调用的组件,如下:

import ConfirmVue from '@/components/Confirm'

const Confirm = {}
let zIndex = 1
Confirm.install = Vue => {
  // 使用vue构造器,创建子类,将Vue组件作为Vue.extend的参数
  const ConfirmInstance = Vue.extend(ConfirmVue)
  let currentConfirm
  const initInstance = () => {
    // 实例化
    currentConfirm = new ConfirmInstance()
    // 挂载到body上
    document.body.appendChild(currentConfirm.$mount().$el)
    // 确保后面出现的弹窗位于先前一个的上层
    currentConfirm.$mount().$el.style.zIndex = zIndex + 100
  }

  // 覆盖蚂蚁金服的确认框组件
  Vue.prototype.$confirm = (options) => {
    if (!currentConfirm) {
      initInstance()
    }

    // 组件设置
    options.title =  options.title === undefined ? '系统提示' : options.title
    options.content = options.content === undefined ? '提示内容' : options.content
    options.sureBtnText = options.sureBtnText === undefined ? '确定' : options.sureBtnText
    options.cancelBtnText = options.cancelBtnText === undefined ? '取消' : options.cancelBtnText

    // 展示弹窗
    currentConfirm.show()

    // 避免多次绑定事件
    currentConfirm.$off('ok')
    currentConfirm.$off('cancel')

    // 绑定弹窗确定事件
    currentConfirm.$on('ok', () => {
      options.onOk && options.onOk(false)
    })

    // 绑定弹窗取消事件
    currentConfirm.$on('cancel', () => {
      options.onCancel && options.onCancel(false)
    })

    Object.assign(currentConfirm, options)
    return currentConfirm
  }
}

export default Confirm

第三步,调用示例,如下:

this.$confirm({
    title: '系统提示',
    onOk: () => {
      alert('确定了')
    },
    onCancel() {
      alert('取消了')
    }
})

效果如图:

image.png

最后说句题外话吧,正所谓前人栽树,后人乘凉,写程序也不例外呢!之所以会有这个知识储备,也得益于帅气的HJX同学呢!

以上内容如有纰漏或更优解,望不吝赐教~