Vue.js開發一個全局調用的MessageBox組件

前言

目前在開發我的博客項目中,一開始就沒準備使用一些如今比較流行的UI庫(畢竟是我的項目,多練練手仍是好的),因此須要本身開發幾個全局組件,這裏以MessageBox爲例記錄下Vue.js如何開發全局組件。css

源碼

Talk is cheap. Show me the code.html

組件模板

// /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官方文檔中有開發插件的介紹。具體實現代碼以下:vue

// /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);

頁面調用

按照以前定義好的方法,能夠在各個頁面中愉快的調用該組件了。git

this.$msgBox.showMsgBox({
    title: '添加分類',
    content: '請填寫分類名稱',
    isShowInput: true
}).then(async (val) => {
    // ...        
}).catch(() => {
    // ...
});

最後來張效果圖

圖片描述

相關文章
相關標籤/搜索