原文地址https://blog.phyer.cn/article...

分享一个使用vue单文件组件写的一个弹出提示消息的组件

效果

Edge下的测试
演示视频

代码

popup.vue

<template>    <div>        <div :class="['ani', state]"            @mouseenter="toggle_pause(true)"            @mouseleave="toggle_pause(false)"        >            <div class="bg"></div>            <div class="show">                <span></span>                <a>{{msg}}</a>            </div>            <span @click="close"></span>            <div class="process"></div>        </div>    </div></template><script>import $ from 'jQuery';window.$ = $;window.jQuery = $;import '../../../static/js_lib/velocity.min';export default {    data (){        return {            state: 'suc',            msg: '无消息',            // 弹出/隐藏 延迟和动画            pop_delay: 300,            pop_easing: 'ease-out',            // 展示时间            duration: 3000,        }    },    methods: {        show (data){            let vue_ = this;            // 更改信息            this.msg = data.msg;            this.state = data.state;            let poper = this.$el.querySelector('.ani'),                timer = this.$el.querySelector('.process');            // 重置popup和timing状态            $(poper).velocity('stop', true);            $(timer).velocity('stop', true);            $(poper).velocity({left: '100%'}, 0, ()=>{                $(timer).velocity({left: '0'}, 0, ()=>{                   // 开始弹出动画                    $(poper).velocity({left: '0'}, vue_.pop_delay, vue_.pop_easing,                        ()=>{                            // 开始计时动画                            $(timer).velocity({left: '-100%'}, vue_.duration, 'linear',                                ()=>{                                    // 开始收回动画                                    $(poper).velocity({left: '100%'}, vue_.pop_delay, vue_.pop_easing,                                        ()=>{                                            // 计时器归零                                            timer.style.left = '0';                                        }                                    )                                }                            )                        }                    )                });            });        },        close (){            let vue_ = this,                poper = this.$el.querySelector('.ani'),                timer = this.$el.querySelector('.process');            // 停止动画            $(poper).velocity('stop', true);            $(timer).velocity('stop', true);            // 开始隐藏动画            timer.style.left = '0';            $(poper).velocity({left: '100%'}, vue_.pop_delay, vue_.pop_easing, ()=>{                timer.style.left = '0'            })        },        toggle_pause (b){            let timer = this.$el.querySelector('.process');            if (b){                $(timer).velocity('pause');            }else{                $(timer).velocity('resume');            }        }    }}</script><style lang="scss">    #popup{        max-width: 50%;        position: fixed;        right: 0;        top: 0;        >.ani{            border-radius: 0.4rem 0.4rem 0 0;            box-shadow: 0 0 0.6rem rgba(0, 0, 0, 0.4);            padding: 1rem 2rem;            margin: 1rem;            overflow: hidden;            position: relative;            left: 100%;            >.bg{                width: 100%;                height: 100%;                border-radius: inherit;                z-index: 1;                position: absolute;                left: 0;                top: 0;            }            >.show{                z-index: 2;                border-radius: inherit;                >span{                    &:before{                        font-family: var(--iconfont);                        font-size: 1.4rem;                        margin-right: 1rem;                    }                }                >a{                    font-size: 0.8rem;                    line-height: 1.2rem;                }            }            @each $cls,$col,$f in (warn, #ffe99a, #ffb100), (suc, #b5ffca, #5478ff), (err, #ffc4ba, #ff0012){                &.#{$cls}{                    >.bg{                        background: $col;                    }                    >.show >span:before{                        color: $f;                        content: var(--i-#{$cls});                    }                }            }            >span{                position: absolute;                top: 0.3rem;                right: 0.3rem;                line-height: 0.7rem;                cursor: pointer;                color: #666;                z-index: 2;                &:before{                    font-family: var(--iconfont);                    content: var(--i-close);                    font-size: 0.6rem;                }                &:hover{                    color: red;                    font-weight: bold;                }            }            >.process{                width: 100%;                height: 0.2rem;                background: #c300ff;                position: absolute;                bottom: 0;                left: 0;                z-index: 2;            }        }    }</style>

util.js

    import popup from '../../components/popup/popup.vue';    window.header_vue = new Vue({        el: '#popup',        data: {        },        components: {popup},        methods: {            pop_data (data) {                this.$refs.popup.show(data)            }        }    });

在使用的地方只需要这样写:

... ...header_vue.pop_data({state: 'suc', msg: '成功'})... ...

velocityjs

此组件的动画基于velocityjs,它是一个兼容性较强,性能强和可自定义的前端动画框架,有兴趣可以了解一下。