我是vuetify UI框架下进行的项目。不引入框架的话,BlogMessage.vue下的样式文件需要自己按照需求写。

1、结构

// src/components/Message

Message文件夹下有两个文件,BlogMessage.vue和index.js文件

2、 BlogMessage.vue

<template>
  <div>
    <v-snackbar v-model="visible" :timeout="duration" top :color="color">
      {{ message }}
      <v-btn color="blue" text @click="visible = false">
        Close
      </v-btn>
    </v-snackbar>
  </div>
</template>
<script>
// 定义每一个 type 对应的 class 类名
const typeClass = {
  success: "#4caf50",
  error: "#ff5252",
  info: "#2196f3",
  default: "info"
};
export default {
  name: "messageMain",
  // 定义的是默认数据, 默认值
  data() {
    return {
      visible: false, // 控制 DOM 显示隐藏
      type: "success", // 默认 type 值为 default
      message: "default", // 默认的 message 为空, 由外部传入
      duration: 2000 // 默认显示时间为 2000ms
    };
  },
  computed: {
    // 如果外部传入 icon 则使用外部的 icon, 如果没有. 则使用 type 值对应的 icon
    color() {
      return typeClass[this.type];
    }
  }
};
</script>

3、index.js文件内容

import Vue from "vue"; // 引入 Vue
import BlogMessage from "./BlogMessage.vue"; // 引入上边定义好的 message 模板
const MessageBox = Vue.extend(BlogMessage); // 使用 Vue.extend 来创建一个构造器
let instance; // instance 变量用来保存实例
let timer = null; // timer 变量用来保存定时器
// 定义一个 function, 参数为 options, 默认为一个对象
const Message = function(options = {}) {
  // 如果当前处在服务器端, 则直接返回
  if (Vue.prototype.$isServer) return;
  // 如果当前定时器已开启, 说明页面上已经有一个 message-box 了, 则不能再继续创建新的 message-box
  if (timer) return;
  // 对 options 做处理, 如果直接传入 string, 则使其保存在 options 的 message 属性上
  if (typeof options === "string") {
    options = {
      message: options
    };
  }
  // 初始化实例, 并将 options 作为新的 data 传入, Vue 会将 options 合并到原有的 data 上, 覆盖原有的默认值, 但是, 在 options 中没有设置的是不会被改变的
  instance = new MessageBox({
    data: options
  });
  // 调用 $mount 方法, 将当前实例渲染为真实 DOM, 生成 $el,, 如果不执行这一步, 将拿不到 $el 的值, 但是不指定 DOM 节点接管当前实例
  instance.vm = instance.$mount();
  // 使用原生 JS 的 API 将当前实例的真实 DOM 追加到 body 中
  document.body.appendChild(instance.vm.$el);
  // 实例上的 vm 就是我们的 Vue 组件, 所以我们可以通过 vm 访问到当前实例中的所有属性
  // 将 visible 设置为 true, 即显示当前 message-box
  instance.vm.visible = true;
  // 开启定时器
  timer = setTimeout(() => {
    // 在时间结束后将当前实例手动卸载
    instance.vm.$destroy();
    // 使用原生 API 将当前实例生成的 DOM 节点在真实的 DOM 树中删除
    instance.vm.$el.parentNode.removeChild(instance.vm.$el);
    // 清除定时器
    timer = null;
  }, instance.vm.duration);
  // 定时器的时间使用 vm 中定义的时间
  return instance.vm;
};
// 最终抛出一个对象, 对象上我们可以使用 install 来扩展 Vue 的插件
// 当我们的对象上有 install 方法的时候, 它接收第一个参数为 Vue,
// 我这里为了方便使用, 还在当前抛出的对象上定义了一个 message 方法, 为了方便在 axios 的拦截器中使用;
export default {
  message: Message,
  install(Vue) {
    Vue.prototype.$message = Message;
    Vue.message = Message;
  }
};

4、在项目main.js中引入注册

import Message from "./components/Message";
Vue.use(Message); // 因为我们的对象上定义了 install 方法, 所以可以直接调用 Vue 的 use 方法

Vue.config.productionTip = false;

new Vue({
  router,
  store,
  vuetify,
  render: h => h(App)
}).$mount("#app");

5、在其他地方使用的时候

直接调用this.$message({
type: “error”,
message: “消息内容”,
duration: 6000
})

<v-btn color="grey" @click="handleClick">
      点击
    </v-btn>
。。。。。。。。。。。代码省略
handleClick() {
      this.$message({
        type: "error",
        message: "什么好"
      });

参考连接https://www.h3399.cn/201907/704000.html

Logo

前往低代码交流专区

更多推荐