乐趣区

popupvue消息提示组件

原文地址 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,它是一个兼容性较强,性能强和可自定义的前端动画框架,有兴趣可以了解一下。

退出移动版