最近体验了下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>

我随便写了三种使用方式示例

  1. 鼠标定位
  2. 全屏随机
  3. 屏幕队列

代码中有部分地方用到了 lodash 库,你可以安装下这个库或者修改下自己实现
下面看看效果图:

Vue开发个简单的Toast组件新手入门实例

Vue开发个简单的Toast组件新手入门实例

Vue开发个简单的Toast组件新手入门实例

功能应该还是比较完善了,根据自己的需求再修改或搭配下参数就好了。

Logo

前往低代码交流专区

更多推荐