【uni-app】实现h5环境下页面弹出通知消息

最近用uin-app的做项目,要弄推送通知的,由于H5不能控制通知栏,便退而求其次要在页面显示通知,虽然觉得有点鸡肋,但这是需求,只能埋头敲代码,以为是要每个页面都显示,所以自己画了一个页面,在全局挂载到body下,以下是效果图,配合使用【前端】node+express模拟websocket通信更加

效果GIF.gif

在文件夹下创建了这两个文件


image.png

notify-push-model.vue

<template>
    <!-- 通知栏 -->
    <view class="notify-push-model fadeIn" :class="[type, translate]" v-if="visible" @touchstart="start" @touchend="end">
        <view>{{ text }}</view>
        <view class="more-text" v-if="isShowMore">查看更多>></view>
        <view class="notify-push-model-close cross" @click.stop="onClose"></view>
    </view>
</template>

<script>
export default {
    props: {
        duration: {
            // 显示时间
            type: Number,
            default: 3000
        },
        transition: {
            // 是否开启动画
            type: Boolean,
            default: true
        }
    },
    data() {
        return {
            visible: false,
            type: '',
            text: '',
            translate: '',
            startData: {},
            closeDuration: 300,
            isShowMore: false
        };
    },
    computed: {
        isRing() {
            return this.$store.state.isRing; //是否铃声
        },
        isNotificationBar() {
            return this.$store.state.isNotificationBar; //是否通知
        },
        isShock() {
            return this.$store.state.isShock; //是否震动
        }
    },
    methods: {
        // 通知音效
        playAudio() {
            const innerAudioContext = uni.createInnerAudioContext();
            innerAudioContext.autoplay = true;
            innerAudioContext.src = '/static/audio/notify-2.mp3';
            innerAudioContext.onPlay(() => {
                // console.log('通知音效 - 播放');
            });
            innerAudioContext.onError(res => {
                console.log('通知音效 - 报错',res.errCode);
            });
        },

        // 设备震动
        onVibrate() {
            let vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate;
            if (vibrate) {
                navigator.vibrate([500, 300, 400, 300]);
            } else {
                console.warn('不支持设备震动!');
            }
        },

        open() {
            //开启通知栏时
            if (this.isNotificationBar) {
                this.visible = true;
                if (this.isRing) {
                    setTimeout(() => {
                        this.playAudio();
                    }, 0);
                }
                if (this.isShock) {
                    this.onVibrate();
                }
            }
        },

        // 自动隐藏
        autoHide() {
            setTimeout(() => {
                this.translate = 'top-leave';
                this.close('noMore');
            }, this.duration - this.closeDuration);
        },

        // 隐藏消息通知
        close(type) {
            setTimeout(() => {
                this.translate = '';
                this.visible = false;
                this.isShowMore = type === 'noMore' ? false : true; //如果是自己关闭的就隐藏更多,如果是消息太多关闭之前的就显示更多
            }, this.closeDuration);
        },

        // 关闭按钮
        onClose() {
            this.translate = 'top-leave';
            this.close('noMore');
        },

        // 开始滑动
        start(e) {
            this.startData.clientX = e.changedTouches[0].clientX;
            this.startData.clientY = e.changedTouches[0].clientY;
        },

        // 滑动结束
        end(e) {
            const subX = e.changedTouches[0].clientX - this.startData.clientX;
            const subY = e.changedTouches[0].clientY - this.startData.clientY;
            if (subY > 50 || subY < -50) {
                this.translate = '';
                console.log('上下滑');
            } else {
                if (subX > 100) {
                    //右滑
                    this.translate = 'right-leave';
                    this.close('noMore');
                } else if (subX < -100) {
                    //左滑
                    this.translate = 'left-leave';
                    this.close('noMore');
                } else {
                    this.translate = '';
                    console.log('滑动无效');
                }
            }
        }
    }
};
</script>
<style lang="scss" scoped>
/*弹层动画(从上往下)*/
.fadeIn {
    -webkit-animation: fadeInDown 0.5s;
    animation: fadeInDown 0.5s;
}

@keyframes fadeInDown {
    0% {
        transform: translate3d(0, -100%, 0);
        opacity: 0;
    }
    100% {
        -webkit-transform: none;
        transform: none;
        opacity: 1;
    }
}

.top-leave {
    transform: translateY(-110%);
    transition-timing-function: cubic-bezier(0.36, 0.66, 0.04, 1);
}
.right-leave {
    transform: translateX(110%);
    transition-timing-function: cubic-bezier(0.36, 0.66, 0.04, 1);
}
.left-leave {
    transform: translateX(-110%);
    transition-timing-function: cubic-bezier(0.36, 0.66, 0.04, 1);
}

// 消息通知框
.notify-push-model {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 2000;
    width: 100%;
    height: auto;
    min-height: 50rpx;
    font-size: 30rpx;
    font-family: PingFang-SC-Medium;
    color: #f1f1f1;
    background: rgba($color: #000000, $alpha: 0.8);
    border-radius: 10rpx;
    padding: 25rpx 70rpx 25rpx 30rpx;
    box-sizing: border-box;
    transition-property: width, height, transform, background, font-size;
    transition-duration: 0.3s, 0.3s, 0.3s, 0.3s, 0.3s;
    box-shadow: 0 2rpx 12rpx 0 rgba($color: #000000, $alpha: 0.1);
    // transform: translateY(-100%);
    opacity: 0.9;
}

// 关闭按钮
.notify-push-model-close {
    position: absolute;
    top: 50%;
    right: 0;
    width: 30rpx;
    height: 30rpx;
    padding: 20rpx 20rpx;
    &::before,
    &::after {
        content: '';
        position: absolute;
        display: flex;
        justify-content: center;
        background: #f1f1f1;
        top: 0;
        left: 19rpx;
        width: 30rpx;
        height: 3rpx;
    }
    &::before {
        transform: rotate(45deg);
    }
    &::after {
        transform: rotate(-45deg);
    }
}

// 主要
.notify-push-model.primary {
    color: #f1f1f1;
    background: rgba($color: #0f88eb, $alpha: 1);
    .cross {
        &::before,
        &::after {
            background: #f1f1f1;
        }
    }
}

// 成功
.notify-push-model.success {
    color: #f1f1f1;
    background: rgba($color: #07c160, $alpha: 1);
    .cross {
        &::before,
        &::after {
            background: #f1f1f1;
        }
    }
}

// 警告
.notify-push-model.warning {
    color: #bb9f4c;
    background: rgba($color: #fff0d6, $alpha: 1);
    .cross {
        &::before,
        &::after {
            background: #bb9f4c;
        }
    }
}

// 危险
.notify-push-model.danger {
    color: #f1f1f1;
    background: rgba($color: #f56c6c, $alpha: 1);
    .cross {
        &::before,
        &::after {
            background: #f1f1f1;
        }
    }
}

// 信息
.notify-push-model.info {
    color: #f1f1f1;
    background: rgba($color: #909399, $alpha: 1);
    .cross {
        &::before,
        &::after {
            background: #f1f1f1;
        }
    }
}

.more-text {
    font-size: 24rpx;
    text-align: right;
}
</style>

index.js

import notifyModel from '@/components/notify/notify-push-model'

const notify = {}
notify.install = (vue, options) => {
    const ToastCon = vue.extend(notifyModel)
    const ins = new ToastCon()
    ins.$mount(document.createElement('div'))
    document.body.appendChild(ins.$el)
    vue.prototype.$notify = {
        show(options) {
            if (ins.visible === true) { //如果已经是显示的
                ins.translate = 'top-leave';
                ins.close()
                setTimeout(() => {
                    if (typeof options === 'string') { // 对参数进行判断
                        ins.text = options
                    } else if (typeof options === 'object') {
                        Object.assign(ins, options) // 合并参数与实例
                    }
                    // ins.visible = true
                    ins.open()
                }, ins.closeDuration)

                if (typeof options === 'object' && options.auto) { //3s后自动隐藏
                    ins.autoHide()
                }
            } else {
                if (typeof options === 'string') { // 对参数进行判断
                    ins.text = options
                } else if (typeof options === 'object') {
                    Object.assign(ins, options) // 合并参数与实例
                }
                // ins.visible = true
                ins.open()
            }

        },
        hide() {
            ins.visible = false
            ins.translate = 'top-leave';
            ins.close()
        }

    }
}

export default notify;

main.js


/*==================|-- * 消息推送 * start --|==================*/
// #ifdef H5
import notify from '@/components/notify/index'
Vue.use(notify)
// #endif
/*==================|-- * 消息推送 * end--|==================*/
使用方法
this.$notify.show({ type: 'success', text: '您有新的订单,请注意查收!' });
//or
this.$notify.show('您有新的订单,请注意查收!' );

想模拟下在websocket通信下的状态,请点击这个页面配合使用【前端】node+express模拟websocket通信

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容