Vue.js开发一个全局调用的MessageBox组件

TDon

前言

目前在开发个人博客项目中,一开始就没准备使用一些现在比较流行的UI库(毕竟是个人项目,多练练手还是好的),所以需要自己开发几个全局组件,这里以MessageBox为例记录下Vue.js如何开发全局组件。

源码

Talk is cheap. Show me the code.

组件模板

// /src/components/MessageBox/index.vue
<template>
    <div class="message-box" v-show="isShowMessageBox">
        <div class="mask" @click="cancel"></div>
        <div class="message-content">
        <svg class="icon" aria-hidden="true" @click="cancel">
          <use xlink:href="#icon-delete"></use>
        </svg>
            <h3 class="title">{{ title }}</h3>
            <p class="content">{{ content }}</p>
        <div>
          <input type="text" v-model="inputValue" v-if="isShowInput" ref="input">
        </div>
            <div class="btn-group">
                <button class="btn-default" @click="cancel" v-show="isShowCancelBtn">{{ cancelBtnText }}</button>
                <button class="btn-primary btn-confirm" @click="confirm" v-show="isShowConfimrBtn">{{ confirmBtnText }}</button>
            </div>
        </div>
    </div>
    </template>
    
    <script>
    export default {
      props: {
        title: {
          type: String,
          default: '标题'
        },
        content: {
          type: String,
          default: '这是弹框内容'
        },
        isShowInput: false,
        inputValue: '',
        isShowCancelBtn: {
          type: Boolean,
          default: true
        },
        isShowConfimrBtn: {
          type: Boolean,
          default: true
        },
        cancelBtnText: {
          type: String,
          default: '取消'
        },
        confirmBtnText: {
          type: String,
          default: '确定'
        }
      },
      data () {
        return {
          isShowMessageBox: false,
          resolve: '',
          reject: '',
          promise: '' // 保存promise对象
        };
      },
      methods: {
        // 确定,将promise断定为resolve状态
        confirm: function () {
          this.isShowMessageBox = false;
          if (this.isShowInput) {
            this.resolve(this.inputValue);
          } else {
            this.resolve('confirm');
          }
          this.remove();
        },
        // 取消,将promise断定为reject状态
        cancel: function () {
          this.isShowMessageBox = false;
          this.reject('cancel');
          this.remove();
        },
        // 弹出messageBox,并创建promise对象
        showMsgBox: function () {
          this.isShowMessageBox = true;
          this.promise = new Promise((resolve, reject) => {
            this.resolve = resolve;
            this.reject = reject;
          });
          // 返回promise对象
          return this.promise;
        },
        remove: function () {
          setTimeout(() => {
            this.destroy();
          }, 300);
        },
        destroy: function () {
          this.$destroy();
          document.body.removeChild(this.$el);
        }
      }
    };
    </script>
    <style lang="scss" scoped>
    // 此处省略 ...
    </style>
    

给组件添加全局功能

vue.js官方文档中有开发插件的介绍。具体实现代码如下:

// /src/components/MessageBox/index.js

import msgboxVue from './index.vue';    
// 定义插件对象
const MessageBox = {};
// vue的install方法,用于定义vue插件
MessageBox.install = function (Vue, options) {
  const MessageBoxInstance = Vue.extend(msgboxVue);
  let currentMsg;
  const initInstance = () => {
    // 实例化vue实例
    currentMsg = new MessageBoxInstance();
    let msgBoxEl = currentMsg.$mount().$el;
    document.body.appendChild(msgBoxEl);
  };
  // 在Vue的原型上添加实例方法,以全局调用
  Vue.prototype.$msgBox = {
    showMsgBox (options) {
      if (!currentMsg) {
        initInstance();
      }
      if (typeof options === 'string') {
        currentMsg.content = options;
      } else if (typeof options === 'object') {
        Object.assign(currentMsg, options);
      }
      return currentMsg.showMsgBox()
        .then(val => {
          currentMsg = null;
          return Promise.resolve(val);
        })
        .catch(err => {
          currentMsg = null;
          return Promise.reject(err);
        });
    }
  };
};
export default MessageBox;

全局使用


// src/main.js
import MessageBox from './components/MessageBox/index';
Vue.use(MessageBox);

页面调用

按照之前定义好的方法,可以在各个页面中愉快的调用该组件了。

this.$msgBox.showMsgBox({
    title: '添加分类',
    content: '请填写分类名称',
    isShowInput: true
}).then(async (val) => {
    // ...        
}).catch(() => {
    // ...
});    

最后来张效果图

图片描述

阅读 17k

DON的前端分享
前端开发,也了解一些后端的开发。分享个人项目和开发经验。
906 声望
42 粉丝
0 条评论
906 声望
42 粉丝
文章目录
宣传栏