Vue开发个简单的Toast组件新手入门实例
最近体验了下Vue,Toast都是前端常用组件,顺便写个入门的实例给同是新手入门的同学一个参考吧
废话不多说,直接放码过来了。。。
Toast.vue 组件代码
<template>
<div ref="toast" class="toast" @click="fadeout" :class="classes" :style="styles"><span class="toast-icon"></span><span class="toast-message">{{ message }}</span></div>
</template>
<script>
import lodash from 'lodash'
export default {
name: 'Toast',
data() {
return {
classes: [],
styles: {
color: '#FF5500',
},
}
},
props: {
message: String,
duration: {
type: Number,
default: 2000 // 持续显示的时长,单位 ms 为 0 则不自动消失需手动点击
},
position: {
// 定位,数组格式支持自定义位置,左上比较常用所以顺序为[left, top, right, bottom],
// 单位:px, 若为 0~1 之间的小数时则表示占屏幕的百分比%
// default(){return [.1, .1]},
// 定位,预设 topLeft|topCenter|topRight|centerLeft|center|centerRight|bottomLeft|bottomCenter|bottomRight
default: 'center',
},
zIndex: {
type: Number,
default: 100000
},
maxWidth: {
type: String,
default: '300px', // 最大宽度
},
offset: {
type: Array,
default() {
// 仅用于对预设定位点(如:topLeft|center...)坐标在 [X, Y] 轴的偏移量修正,单位 px
// 作用于 margin-top|margin-left, 可以为负数; > 0 则偏向右下角,< 0 则偏向左上角
return [0, -300]
}
}
},
computed: {
},
methods: {
fadeout() {
this.classes.push('fadeout'); // 淡出效果直接覆盖了 fadein 的 css 设置
lodash.delay(() => this.$destroy(), 500); // 淡出动画结束后再销毁
},
show(){
this.$set(this.styles, 'zIndex', this.zIndex);
this.$set(this.styles, 'maxWidth', this.maxWidth);
if (lodash.isArray(this.position)) {
const [left, top, right, bottom] = this.position;
const resolve = (s, n) => {
if (n !== undefined) this.$set(this.styles, s, (n > 0 && n < 1) ? (n*100) + '%' : n +'px');
};
resolve('top', top);
resolve('right', right);
resolve('bottom', bottom);
resolve('left', left);
}
const isPrePos = lodash.isString(this.position); // 是字符串则认定为默认的预设定位点
if (isPrePos) {
const pos = this.position.toString();
const isC1 = pos.indexOf('center') > -1;
const isC2 = pos.indexOf('Center') > -1;
// 设置预设定位点样式
this.classes.push(pos.replace(/([A-Z])/, (s) => '-' + s.toLowerCase()));
// 居中定位修正
if (isC1 || isC2) {
if (pos === 'center' || isC1) {
this.$set(this.styles, 'marginTop',
((isPrePos ? (this.$refs.toast.clientHeight * -1 / 2) : 0) + this.offset[1]) + 'px');
}
if (pos === 'center' || isC2) {
this.$set(this.styles, 'marginLeft',
((isPrePos ? (this.$refs.toast.clientWidth * -1 / 2) : 0) + this.offset[0]) + 'px');
}
}
}
// 添加淡入效果
this.classes.push('fadein');
this.duration > 0 && lodash.delay(() => {
this.fadeout();
}, this.duration);
},
},
created: function () {
this.$nextTick(function(){
this.show();
});
},
destroyed: function () {
this.$el.parentNode.removeChild(this.$el)
}
}
</script>
<style scoped>
.toast {
display: block;
position: fixed;
padding: .5rem;
font-size: .8rem;
background-color: #FFF;
box-shadow: 0 0 5px rgba(0,0,0,.1);
opacity: 0;
word-break: break-all;
word-wrap: break-word;
}
.toast.top-left {
top: 0;
left: 0;
}
.toast.top-center {
top: 0;
left: 50%;
}
.toast.top-right {
top: 0;
right: 0;
}
.toast.center-left {
top: 50%;
left: 0;
}
.toast.center {
top: 50%;
left: 50%;
}
.toast.center-right {
top: 50%;
right: 0;
}
.toast.bottom-left {
bottom: 0;
left: 0;
}
.toast.bottom-center {
bottom: 0;
left: 50%;
}
.toast.bottom-right {
bottom: 0;
right: 0;
}
.toast.fadein {
opacity: 1;
transition: opacity ease-in .2s;
}
.toast.fadeout {
opacity: 0;
transform: scale(.5);
transition: all ease-in-out .4s;
}
</style>
全局注册及使用方法
ToastTest.vue
<script>
import Vue from "vue"
import lodash from "lodash"
import Toast from "Toast"
let toastTimer;
let toastIndex = 0;
let toastQueueOffset = 0;
const ToastConstructor = Vue.extend(Toast);
Vue.prototype.$toast = function(data) {
document.body.appendChild(new ToastConstructor({
el: document.createElement('div'),
propsData: data
}).$el);
};
export default {
name: "ToastTest",
components: {Toast},
methods: {
showToast(e) {
this.$toast({
message: 'Toast index '+ toastIndex++,
duration: 2000,
position: [e.clientX, e.clientY],
});
},
showToastRand() {
this.$toast({
message: 'Toast index '+ toastIndex++,
duration: 0,
position: [parseInt(Math.random()*(window.innerWidth)), parseInt(Math.random()*window.innerHeight)],
});
},
showToastQueue(e) {
const duration = 2000;
clearTimeout(toastTimer);
toastTimer = setTimeout(() => toastQueueOffset = 0, duration);
this.$toast({
message: 'Toast index '+ toastIndex++,
duration: duration,
position: [e.clientX+100, 45*toastQueueOffset++],
});
}
},
}
</script>
<template>
<div class="articles-ct">
<button class="draft-btn" @click="showToast"> + 鼠标 </button>
<br><br>
<button class="draft-btn" @click="showToastRand"> + 随机 </button>
<br><br>
<button class="draft-btn" @click="showToastQueue"> + 队列 </button>
</div>
</template>
我随便写了三种使用方式示例
- 鼠标定位
- 全屏随机
- 屏幕队列
代码中有部分地方用到了 lodash 库,你可以安装下这个库或者修改下自己实现
下面看看效果图:
功能应该还是比较完善了,根据自己的需求再修改或搭配下参数就好了。