Vue.extend和Vue.use的应用

67 阅读1分钟

image.png

MessageBox.vue

<template>
  <div :class="['message-box', type]">
    <div class="inner">
      <header class="header">
        <h1 class="title">{{ title }}</h1>
        <span class="close-btn" @click="hideMessageBox">x</span>
      </header>
      <div class="content">{{ content }}</div>
    </div>
  </div>
</template>
<script>
export default {
  name: 'MessageBox',
  components: {
  },
  props: {
    title: {
      type: String,
      default: 'This is a TITLE'
    },

    content: {
      type: String,
      default: 'This is CONTENT'
    },

    type: {
      type: String,
      default: 'primary',
      validator (value){
        return ['primary', 'success', 'warn', 'danger'].includes(value)
      }
    }
  },
  data() {
    return {
        
    }
  },
  created(){
      
  },
  methods: {
    hideMessageBox() {
      this.$messageBox.hide(() => {
        console.log("HIDE");
      })
    }
  },
}
</script>
<style scoped lang="scss">
  h1 {
    margin: 0;
  }
  
  .message-box {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0,0,0, .5);

    .inner {
      position: absolute;
      top: 100px;
      left: 50%;
      width: 500px;
      margin-left: -250px;
      background-color: #fff;
      box-shadow: 1px 3px 5px #ededed;
      border-radius: 5px;
      // overflow: hidden;

      .header {
        height: 44px;
        padding: 0 10px;
        line-height: 44px;
        box-sizing: border-box;

        .title {
          float: left;
          font-size: 16px;
        }

        .close-btn {
          float: right;
          cursor: pointer;
        }
      }

      .content {
        padding: 20px;
        box-sizing: border-box;
      }
    }

    &.primary {
      header {
        background-color: blue;
        color: #fff;
      }
    }

    &.success {
      header {
        background-color: green;
        color: #fff;
      }
    }

    &.warn {
      header {
        background-color: orange;
        color: #333;
      }
    }

    &.danger {
      header {
        background-color: red;
        color: #fff;
      }
    }

  }



</style>

MessageBox下的index.js

import _MessageBox from "./MessageBox";


export default {

  install(Vue) {

    let messageBox = null;
    Vue.component(_MessageBox.name, _MessageBox);
    console.log('_MessageBox:', JSON.parse(JSON.stringify(_MessageBox)));

    Vue.prototype.$messageBox = {
      show,
      hide,
      primary,
      success,
      warn,
      danger
    }

    function primary(props, callback) {
      this.show({ ...props, type: 'primary'}, callback)
    }

    function success(props, callback) {
      this.show({ ...props, type: 'success'}, callback)
    }

    function warn(props, callback) {
      this.show({ ...props, type: 'warn'}, callback)
    }

    function danger(props, callback) {
      this.show({ ...props, type: 'danger'}, callback)
    }

    function show(props, callback) {
      if (!messageBox) {
        const MessageBox = Vue.extend({
          render (h) {
            return h('message-box', { props })
          }
        });

        messageBox = new MessageBox();
        this.vm = messageBox.$mount();
        document.body.appendChild(this.vm.$el);
        callback && callback();
      }
    }

    function hide(callback) {
      document.body.removeChild(this.vm.$el);
      messageBox.$destroy();
      messageBox = null;
      this.vm = null;
      callback && callback();
    }
  }
}

MyUI下的index.js

import MessageBox from "./MessageBox";


export {
  MessageBox
}

脚手架中main.js文件

// 导入根据位置自己自行更改
import { MessageBox } from './views/dashboard/MyUI'
// Vue.use() 插件,会自行调用install()函数,自行组件挂载
Vue.use(MessageBox)

index使用MessageBox

<template>
  <div class="dashboard-container">
    <button @click="openMessageBox"> show </button>
    <button @click="openMessageBoxPrimary"> primary </button>
    <button @click="openMessageBoxSuccess"> success </button>
    <button @click="openMessageBoxWarn"> warn </button>
    <button @click="openMessageBoxDanger"> danger </button>
  </div>
</template>

<script>
export default {
  name: 'Dashboard',
  components: {
  },
  computed: {
    
  },
  methods: {
    openMessageBox() {
      this.$messageBox.show({
        title: "标题",
        content: "内容",
        type: "success"
      }, () => {
        console.log("SHOW");
      })
    },


    openMessageBoxPrimary() {
      this.$messageBox.primary({
        title: "标题",
        content: "内容",
      })
    },

    openMessageBoxSuccess() {
      this.$messageBox.success({
        title: "标题",
        content: "内容",
      })
    },

    openMessageBoxWarn() {
      this.$messageBox.warn({
        title: "标题",
        content: "内容",
      })
    },

    openMessageBoxDanger() {
      this.$messageBox.danger({
        title: "标题",
        content: "内容",
      })
    },


  }
}
</script>

<style lang="scss" scoped></style>