前端时间项目需要个预览功能 我的设计是给预览按钮添加自定义指令然后赋予预览功能 自定义指令就没什么可说的了 但是要在自定义指令里去调用预览组件就难到我了 当然最后也是实现了的 但是代码就丑陋了些 这里也就不现眼了 然后今天有看到大佬发的文章 代码也是美妙的狠 所以就爬下来 原文在最下面有连接

下面实现一个简易的message弹窗组件
Message/index.vue

<template>  <div class="wrap">    <template v-for="item in notices">      <transition name="fade" :key="item._name">        <div class="message" :class="item.type">          <div class="content">{{item.content}}</div>        </div>      </transition>    </template>  </div></template>
<script>// 默认选项const DefaultOptions = {  duration: 1500,  type: "info",  content: "这是一条提示信息!"};let mid = 0;export default {  data() {    return {      notices: []    };  },  methods: {    add(notice = {}) {      // name标识 用于移除弹窗      let _name = this.getName();      // 合并选项      notice = Object.assign(        {          _name        },        DefaultOptions,        notice      );      this.notices.push(notice);      setTimeout(() => {        this.removeNotice(_name);      }, notice.duration);    },    getName() {      return "msg_" + mid++;    },    removeNotice(_name) {      let index = this.notices.findIndex(item => item._name === _name);      this.notices.splice(index, 1);    }  }};</script>
<style lang="scss" scoped>.wrap {  position: fixed;  top: 50px;  left: 50%;  display: flex;  flex-direction: column;  align-items: center;  transform: translateX(-50%);}.message {  --borderWidth: 3px;  min-width: 240px;  max-width: 500px;  margin-bottom: 10px;  border-radius: 3px;  box-shadow: 0 0 8px #ddd;  overflow: hidden;}.content {  padding: 8px;  line-height: 1.3;}.message.info {  border-left: var(--borderWidth) solid #909399;  background: #f4f4f5;}.message.success {  border-left: var(--borderWidth) solid #67c23a;  background: #f0f9eb;}.message.error {  border-left: var(--borderWidth) solid #f56c6c;  background: #fef0f0;}.message.warning {  border-left: var(--borderWidth) solid #e6a23c;  background: #fdf6ec;}.fade-enter-active,.fade-leave-active {  transition: opacity 0.5s;}.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {  opacity: 0;}</style>

Message/index.js

import Vue from 'vue'import Index from './index.vue'let messageInstance = nulllet MessageConstructor = Vue.extend(Index) // 构造子类let init = () => {    messageInstance = new MessageConstructor() // 实例化组件    // $mount可以传入选择器字符串,表示挂载到该选择器    // 如果不传入选择器,将渲染为文档之外的的元素,你可以想象成 document.createElement()在内存中生成dom    messageInstance.$mount()     // messageInstance.$el获取的是dom元素    document.body.appendChild(messageInstance.$el)}/** * 单例且惰性 */export let caller = (options) => {    if (!messageInstance) {        init(options)    }    messageInstance.add(options)}export default {    // 返回 install 函数 用于 Vue.use 注册    install(vue) {        vue.prototype.$message = caller    }}

main.js

import Message from '@/components/Message/index.js'Vue.use(Message)

两种使用使用方式

      /**       * 在.js文件里这样用       */      import { caller } from "@/components/Message/index.js";      caller({        type: "success",        content: "成功信息提示",        duration: 3000      });            /**       * 在.vue文件里这样用       */      this.$message({        type: "success",        content: "成功信息提示",        duration: 3000      });

细节主要集中在Message/index.js这个文件里
主要是通过Vue.extend这个全局是api和这个vm.$mount实例的api去实现的
原文10个Vue开发技巧助力成为更好的工程师