notice.vue 5.04 KB
<template>
    <transition :name="transitionName" @enter="handleEnter" @leave="handleLeave">
        <div :class="classes" :style="styles">
            <template>
                <div :class="[baseClass + '-content']" ref="content">
                    <div :class="[baseClass + '-content-text']" v-html="content"></div>
                    <a :class="[baseClass + '-close']" @click="close" v-if="closable">
                        <i class="icon icon-close-tip"></i>
                    </a>
                </div>
            </template>
        </div>
    </transition>
</template>
<script>
    export default {
        props: {
            prefixCls: {
                type: String,
                default: ''
            },
            duration: {
                type: Number,
                default: 1.5
            },
            type: {
                type: String
            },
            content: {
                type: String,
                default: ''
            },
            styles: {
                type: Object,
                default: function() {
                    return {
                        right: '50%'
                    };
                }
            },
            closable: {
                type: Boolean,
                default: false
            },
            className: {
                type: String
            },
            name: {
                type: String,
                required: true
            },
            onClose: {
                type: Function
            },
            transitionName: {
                type: String
            }
        },
        data () {
            return {
                withDesc: false
            };
        },
        computed: {
            baseClass () {
                return `${this.prefixCls}-notice`;
            },
            classes () {
                return [
                    this.baseClass,
                    {
                        [`${this.className}`]: !!this.className,
                        [`${this.baseClass}-closable`]: this.closable,
                        [`${this.baseClass}-with-desc`]: this.withDesc
                    }
                ];
            },
            contentClasses () {
                return `${this.baseClass}-content`;
            }
        },
        methods: {
            clearCloseTimer () {
                if (this.closeTimer) {
                    clearTimeout(this.closeTimer);
                    this.closeTimer = null;
                }
            },
            close () {
                this.clearCloseTimer();
                this.onClose();
                this.$parent.close(this.name);
            },
            handleEnter (el) {
                if (this.type === 'message') {
                    el.style.height = el.scrollHeight + 'px';
                }
            },
            handleLeave (el) {
                if (this.type === 'message') {
                    if (document.getElementsByClassName('blk-message-notice').length !== 1) {
                        el.style.height = 0;
                        el.style.paddingTop = 0;
                        el.style.paddingBottom = 0;
                    }
                }
            }
        },
        mounted () {
            this.clearCloseTimer();

            if (this.duration !== 0) {
                this.closeTimer = setTimeout(() => {
                    this.close();
                }, this.duration * 1000);
            }

            if (this.prefixCls === 'blk-notice') {
                this.withDesc = this.$refs.content.querySelectorAll(`.${this.prefixCls}-desc`)[0].innerHTML !== '';
            }
        },
        beforeDestroy () {
            this.clearCloseTimer();
        }
    };
</script>
<style lang="scss">
    .blk-message {
        font-size: 24px;
        position: fixed;
        z-index: 1010;
        width: 100%;
        top: 50px;
        left: 0;
        pointer-events: none;

        &-notice {
            padding: 8px;
            text-align: center;
            transition: height .3s ease-in-out, padding .3s ease-in-out;

            &:first-child {
                 margin-top: -8px;
            }

            .icon-default-tip {
                color: #2db7f5;
            }

            .icon-error-tip {
                color: #ed3f14;
            }

            .icon-success-tip {
                color: #19be6b;
            }
        }

        &-notice-content {
            display: inline-block;
            pointer-events: all;
            padding: 8px 16px;
            border-radius: 4px;
            box-shadow: 0 1px 6px rgba(0, 0, 0, .2);
            background: #fff;
            position: relative;
            &-text{
                 display: inline-block;
            }
        }

        &-notice-closable{
            .blk-message-notice-content-text{
                padding-right: 32px;
            }
        }

        .icon {
            margin-right: 8px;
            font-size: 26px;
            top: 1px;
            position: relative;

            &.icon-close-tip {
                font-size: 30px;
            }
        }
    }
</style>