模仿elment 的Message

elment 有一个Message 可以全局提示的控件很是羡慕,但是作为一位后端人员又不想搞太多前端css,喜欢用vuetify,但是没有全局Message,只好自己动手实现一个了。

.先看一下效果,成功提示框:

vue3用element和antd_vue3用element和antd


失败提示框:

vue3用element和antd_Vue_02


接下来让我们一步步实现

首先在src/commponents/下创建Message目录,并在Message目录下创建

Message.vue和index.js文件,文件位置如下:

vue3用element和antd_sed_03


Message.vue的代码如下:

<template>
	<transition name="message-fade">
		<div class="message" :class="typeClass" role="alert" v-show="visible">
			<p class="message__content">
				<v-icon large :color="color" small=true>{{icon}}</v-icon>   {{message}}
			</p>
		</div>
	</transition>
</template>

<script>
	export default {
		name: 'message',

		data() {
			return {
				visible: false,
				duration: 2000,
				message: '',
				timer: null,
				closed: false,
				color: "",
				icon: "",
				typeClass:""
			}
		},

		watch: {
			closed(val) {
				if (val) {
					this.visible = false
					this.$el.addEventListener('transitionend', this.destroyElement)
				}
			}
		},

		methods: {
			destroyElement() {
				this.$el.removeEventListener('transitionend', this.destroyElement)
				this.$destroy(true)
				this.$el.parentNode.removeChild(this.$el)
			},

			startTimer() {
				if (this.duration > 0) {
					this.timer = setTimeout(() => {
						if (!this.closed) {
							this.close()
						}
					}, this.duration)
				}
			},

			close() {
				this.closed = true
			}
		},

		mounted() {
			// 开始定时器
			this.startTimer()
		}
	}
</script>

<style scoped>
	.message {
		min-width: 380px;
		box-sizing: border-box;
		border-radius: 4px;
		border-width: 1px;
		border-style: solid;
		/* border-color: #ebeef5; */
		position: fixed;
		left: 50%;
		top: 20px;
		transform: translateX(-50%);
		/* background-color: #edf2fc; */
		transition: opacity .3s, transform .4s;
		overflow: hidden;
		padding: 15px 15px 15px 20px;
		display: flex;
		align-items: center
	}

	.message--success {
		background-color: #f0f9eb;
		border-color: #e1f3d8;
		color: #67c23a;
	}

	.message--error {
	background-color: #FFCCFF;
	border-color: #FFCCFF;
	color: #CC0033;
	}

	.message p {
		margin: 0
	}

	.message__content {
		padding: 0;
		font-size: 14px;
		line-height: 1;
	}

	.message-fade-enter,
	.message-fade-leave-active {
		opacity: 0;
		transform: translate(-50%, -100%)
	}
</style>

index中的代码如下:

import Vue from 'vue'
import Main from './Message.vue'

let MessageConstructor = Vue.extend(Main)

let instance
let instances = []
let seed = 1
const Message = function (options,color,icon,typeClass) {
  options = options || {}
  if (typeof options === 'string') {
    options = {
      message: options,
	  color:color,
	  icon:icon,
	  typeClass:typeClass
    }
  }
  let id = 'message_' + seed++
  instance = new MessageConstructor({
    data: options
  })
  instance.id = id
  instance.vm = instance.$mount()
  document.body.appendChild(instance.vm.$el)
  instance.vm.visible = true
  instance.dom = instance.vm.$el
  instance.dom.style.zIndex = 10000
  instances.push(instance)
  return instance.vm
}

Message.success = function(option){
	Message(option,"#67c23a","beenhere","message--success")
}
Message.error = function(option){
	Message(option,"#CC0033","mdi-backspace","message--error")
}

Message.close = function (id) {
  for (let i = 0, len = instances.length; i < len; i++) {
    if (id === instances[i].id) {
      instances.splice(i, 1)
      break
    }
  }
}

Message.closeAll = function () {
  for (let i = instances.length - 1; i >= 0; i--) {
    instances[i].close()
  }
}

export default Message

由于某些原因未实现警告框,如果需要添加,请在Message.vue中的style添加如下:【请改变下列颜色,不要原封不动】

.message--alert {
		//背景颜色
		background-color: #f0f9eb;
		//边框颜色
		border-color: #e1f3d8;
		//文字颜色
		color: #67c23a;
	}

index.js中添加如下,

Message.alert= function(option){
	//请更改第二个和第三个参数,第三个参数是图标,就像success的‘√’,第二个参数是图标的颜色
	Message(option,"#67c23a","beenhere","message--alert")
}

不过,警告框好像没什么作用,那么如上就当作我在帮忙讲解一下这些内容吧,接下来讲一下怎么用

首先需要在main.js中注册

import Message from './components/Message/index.js'
//引入这个是为了解决有时候图标展示不正常,可以先注释了尝试一下
import 'material-design-icons-iconfont/dist/material-design-icons.css'

Vue.prototype.$message = Message

第二个参数亲测不加会有些图标展示不正常或者不出现,详细解决办法请参考部分图标展示不正常 也可以先不解决这个问题,看一下正常不,不正常在返回来解决这个问题,也很简单【温馨提示:在进入上述链接执行npm命令后我会出现node_modules中axios引用被删除的问题,本着不求甚解的精神,为了以防万一,建议首先将这个文件夹复制出来,在执行之后如果被删除,粘贴进去即可!】
接下来就可以在想使用的地方使用了:如下

//成功提示
this.$message.success(`success这是一条消息`)
//失败提示
this.$message.error(`error这是一条消息`)

还有一个问题,在使用拦截器interceptors的时候,做统一异常处理的时候回调用this.$message.error(error这是一条消息) 的时候没有效果,这个是因为this都找不到,这个时候如下操作:

//导入/components/Message/index.js
import Message from '../components/Message/index.js'

然后可以使用Message.error();来进行调用。
统一异常处理本博文就不进行讲述了,大家可以去自己找一下,如有问题可以联系博主,我看到会尽力解决的