Vue2-Vue.extend实现MessageBox-进阶版

214 阅读2分钟

使用 Vue.extend 实现 messageBox 的步骤如下:

(1)创建 MessageBox 组件:定义一个消息框组件 MessageBox.vue ,用于显示提示信息并等待用户确认或取消操作。

(2)创建 MessageBox 构造器:首先使用 Vue.extend 创建 MessageBox 的子类构造器,接着定义 messageBox 函数接收消息、标题和配置参数,在函数内部返回一个 Promise 根据用户操作结果 resolvereject 。最后export default 包含 install 方法的对象,以便在Vue实例中全局调用 messageBox 方法。

(3)引入 MessageBox :使用 Vue.use(messageBox)安装全局组件。

1# 创建 MessageBox 组件:./messagebox/MessageBox.vue

<template>
  <transition name="extends">
    <div v-show="visible" id="messageBox" @click="closeModal">
      <div class="contain">
        <header>
          <i class="el-icon-close" v-if="showClose" @click="close"></i>
        </header>
        <main>
          <div>
            <img :src="getImageUrl()" />
          </div>
          <div class="content">
            <h3 v-if="title">{{ title }}</h3>
            <p v-if="dangerouslyUseHTMLString" v-html="message"></p>
            <p v-else :class="{ large: !title }">{{ message }}</p>
          </div>
        </main>
        <footer>
          <el-button v-if="showCancelButton === true" @click="close">{{ cancelButtonText }}</el-button>
          <el-button type="primary" @click="confirm">{{ confirmButtonText }}</el-button>
        </footer>
      </div>
    </div>
  </transition>
</template>

<script>
export default {
  name: 'message-box',
  data() {
    return {
      visible: false, // 是否可见
      message: '', // 信息
      title: '', // 标题
      lockScroll: true, // 禁止滑动
      showCancelButton: true, // 显示 cancel 按钮
      dangerouslyUseHTMLString: false, // 使用HTML
      showClose: false, // 显示 close 按钮
      closeOnClickModal: false, // 点击蒙版关闭
      confirmButtonText: '确认', // 确认按钮文本
      cancelButtonText: '取消', // 取消按钮文本
      type: 'success', // success、warning、error、info、question
      callback: null // 
    };
  },
  created() {
    if (this.lockScroll) {
      document.body.classList.add('srcoll-hideen');
    }
    this.$nextTick(() => {
      this.visible = true;
    });
  },
  methods: {
    close() {
      this.visible = false;
      this.callback && this.callback(false);
      this.remove();
    },
    closeModal() {
      if (this.closeOnClickModal) {
        this.close();
      }
    },
    confirm() {
      this.visible = false;
      this.callback && this.callback(true);
      this.remove();
    },
    remove() {
      setTimeout(() => {
        this.$destroy(this);
        document.body.classList.remove('srcoll-hideen');
        this.$el.remove();
      }, 500);
    },
    getImageUrl() {
      return require(`@/assets/${this.type}.svg`);
    }
  }
};
</script>
<style scoped>
.srcoll-hideen {
  overflow: hidden;
}
</style>

2# 创建 MessageBox 构造器:./messagebox/main.js

import Vue from 'vue';
import messageBoxVue from './MessageBox.vue';

// 使用Vue.extend创建一个MessageBox的子类构造器
const MessageBox = Vue.extend(messageBoxVue);

// 定义 messageBox 函数,接收消息、标题和配置作为参数
const messageBox = (message, title, config = {}) => {
  return new Promise((resolve, reject) => {
    // 创建回调函数,根据用户操作结果进行resolve或reject
    const callback = ret => {
      if (ret === true) {
        resolve();
      } else if (ret === false) {
        reject();
      }
    };

    // 使用MessageBox子类构造器创建实例
    const instance = new MessageBox({
      data: {
        message, // 内容
        title, // 标题
        lockScroll: config.lockScroll !== false, // 控制是否锁定页面滚动
        dangerouslyUseHTMLString: !!config.dangerouslyUseHTMLString, // 控制是否使用HTML字符串
        showCancelButton: config.showCancelButton !== false, // 控制取消按钮显示
        showClose: config.showClose !== false, // 控制关闭按钮显示
        confirmButtonText: config.confirmButtonText || '确认', // 确认按钮文本
        cancelButtonText: config.cancelButtonText || '取消', // 取消按钮文本
        type: config.type || 'success', // 弹窗类型
        callback // 回调函数
      }
    });

    // 将实例挂载到DOM并添加到body中
    instance.$mount();
    document.body.appendChild(instance.$el);
  });
};

// 导出一个对象,包含install方法,将messageBox挂载在Vue的prototype上
export default {
  install: Vue => {
    // 将 $messageBox 挂载为 Vue 的全局属性
    Vue.prototype.$messageBox = messageBox; 
  }
};

3# 引入 MessageBox:./main.js

import Vue from 'vue';
import messageBox from './messagebox/main.js';

Vue.use(messageBox);