效果预览

思路

  1. 封装 Snackbar 组件;
  2. 在根路由页面下建立全局 Snackbar 控制器,统一管理 Snackbar;
  3. 通过事件通知全局 Snackbar 控制器显示消息;

实现

1. 封装 Snackbar 组件

project/src/components/snackbar.vue

<template>
<div class="component-snackbar" v-if="value">
<div class="snackbar-content">{{ message }}</div>
<div class="snackbar-close" v-if="closable" @click="close">关闭</div>
</div>
</template> <script>
export default {
name: "component-snackbar",
props: {
value: Boolean, // 调用本组件v-model传入的值
message: String, // 消息内容
closable: { // 是否显示删除按钮
type: Boolean,
default: false
}
},
data: function() {
return {
showTime: 6000, // snackbar显示的时长
timer: null // 定时器
}
},
mounted() {
// 在 showTime 到期后自动关闭snackbar
this.timer = setTimeout(() => {
this.close()
}, this.showTime)
},
methods: {
close() {
// 清除定时器
clearTimeout(this.timer)
// 不能直接在组件中修改props中的数据,因此不能直接修改this.value = false
// 而是实现了在自定义组件中使用v-model,通过外传 input 事件通知调用者自动更新 v-model 传入的值
this.$emit('input', false)
}
}
}
</script> <style lang="less">
.component-snackbar {
width: 400px;
height: 60px;
position: fixed;
right: 10px;
bottom: 10px;
display: flex;
flex-direction: row;
align-items: center;
border-radius: 8px;
background-color: #333333;
box-shadow: 2px 4px 6px 0 rgba(0,0,0,.4);
transition: transform 500ms ease-in;
.snackbar-content {
flex: 1;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
padding: 0 16px;
}
.snackbar-close {
margin: 0 16px;
color: deeppink;
cursor: pointer;
}
}
</style>

2. 全局 Snackbar 控制器

注册事件总线 EventBus;

project/src/main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store' Vue.config.productionTip = false // 创建 Vue 的实例作为事件总线使用,将其挂载到 $eventBus 上,
// 即可在组件中直接使用 this.$eventBus.$emit() 和 this.$eventBus.$on() 来触发/监听事件
Vue.prototype.$eventBus = new Vue() new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')

全局 Snackbar 控制器

全局 Snackbar 控制器在根路由页面下监听 showSnackbar 事件,并维护一个消息列表,通过对事件的监听有序的推入、删除消息,从而达到控制 Snackbar 显示的目的;

project/src/App.vue

<template>
<div id="app">
<router-view /> <!-- 全局 Snackbar 队列 -->
<!-- 根据当前 Snackbar 的 index 动态计算 Y 方向的位移,达到依次排列的目的 -->
<snackbar
v-model="item.show"
:style="{transform: 'translateY(' + -(60+10) * index + 'px)'}"
:message="item.content"
:closable="item.closable"
v-for="(item, index) in messages"
:key="item.id"
@input="onSnackbarClose($event, index)"></snackbar>
</div>
</template> <script>
import Snackbar from './components/snackbar' export default {
name: "app",
components: {
Snackbar
},
data: function() {
return {
messages: [] // 消息队列
}
},
mounted() {
// 全局 Snackbar 控制器事件监听
this.snackbarController()
},
methods: {
snackbarController() {
// 监听 showSnackbar 事件
this.$eventBus.$on('showSnackbar', data => {
// 将收到的message推入messages数组中
this.messages.push({
...data,
show: true
})
})
},
onSnackbarClose(value, index) {
// value 为 Snackbar 组件内部传递出来的
// index 为当前关闭 Snackbar 的 索引
// 删除已关闭的 Snackbar 对应的消息数据
this.messages.splice(index, 1)
}
}
}
</script> <style lang="less">
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
background-color: #212121;
color: #cecece;
font-size: 14px;
}
</style>

3. 调用Snackbar

这是一个模拟触发消息的页面;

project/src/views/snackbar.vue

<template>
<div class="view-snackbar">
<div class="wrap">
<input type="text" v-model="msg" class="msg-input" placeholder="说点什么...">
<div class="btn" @click="showMessage">显示消息</div>
</div>
</div>
</template> <script>
export default {
name: 'view-snackbar',
data: function () {
return {
msg: ''
}
},
methods: {
showMessage() {
// 通过触发 showSnackbar 事件并传递消息参数,从而调用全局 Snackbar
this.$eventBus.$emit('showSnackbar', {
id: new Date().getTime(), // id 用于设置 Snackbar 在 v-for 循环中的 key 属性,避免排序混乱的问题
content: this.msg,
closable: true
})
}
}
}
</script> <style lang="less">
.view-snackbar {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-image: url(https://img.cc0.cn/pixabay/2019102201563350617.jpg/content);
background-repeat: no-repeat;
background-size: cover;
background-position: center;
.wrap {
width: 240px;
}
.msg-input {
width: 100%;
height: 40px;
color: inherit;
background-color: #333333;
border: 2px solid #444444;
border-radius: 8px;
outline: none;
padding: 0 8px;
}
.btn {
width: 120px;
margin: 20px auto;
padding: 8px 0;
text-align: center;
border-radius: 8px;
background-color: deeppink;
cursor: pointer;
user-select: none;
}
}
</style>

4. 总结

通过上述4步就实现了简单的 Vue Snackbar 消息条队列显示,并且依次动画消失,思路还是很清晰的,主要有3个要点:

  • 使用了全局控制器,并通过事件总线 $eventBus 传递消息;
  • 在自定义组件中使用 v-model 实现 Snackbar 的删除;
  • 利用 Snackbar 索引动态计算 Y 方向上的位移实现 Snackbar 的有序排列;

本教程旨在描述思路,实现比较简单,未做过多封装和定制,希望能帮到有需要的童鞋,如发现任何问题,或有更多实现方式,欢迎一起讨论!

5. 改善

可在本版基础上做更多完善,有兴趣的童鞋可以自己玩玩;

  • Snackbar 渐变出现/消失;
  • 多种高度的 Snackbar 混合使用;

本文出处:https://www.cnblogs.com/zhenfengxun/
本文链接:https://www.cnblogs.com/zhenfengxun/p/12452814.html

Vue Snackbar 消息条队列显示,依次动画消失的实现的更多相关文章

  1. 前端基于VUE的v-charts的曲线显示

    目录 前端基于VUE的v-charts的曲线显示 1. 应用背景 2. 分析数据生产者生成 3. 取出数据消费者 4. 前端显示 4.1 安装V-charts插件 4.2 引入veline曲线插件 4 ...

  2. vue 圆形进度条组件解析

    项目简介 本组件是vue下的圆形进度条动画组件 自由可定制,几乎全部参数均可设置 源码简单清晰 面向人群 急于使用vue圆形进度条动画组件的同学.直接下载文件,拷贝代码即可运行. 喜欢看源码,希望了解 ...

  3. Android百度地图开发(五)公交线路详情搜索、多条线路显示

    一.公交线路详情检索 获取公交线路的详情主要分来两步,1.获取公交线路的Uid,2.通过Uid获取公交线路详情. 1.获取公交线路的Uid: /* * 获得公交线路图的Uid,并且根据系Uid发起公交 ...

  4. 让TextView里面的文字逐个显示的动画效果实现(1)

    最近使用TextView时想要实现里面的文字逐个显示的动画效果,就如同打字一样. 主要实现思想:新建一个TextView的派生类,先将要逐个显示的字符串保存变量 mOriginalStr 中,然后启动 ...

  5. HTML5效果:Canvas 实现圆形进度条并显示数字百分比

    实现效果 1.首先创建html代码 <canvas id="canvas" width="500" height="500" styl ...

  6. RabbitMQ基础概念(消息、队列、交换机)

    1.消息的确认 RabbitMQ需要对每一条发送的消息进行确认.消费者必须通过AMQP的basic.ack命令显式地向RabbitMQ发送一个确认,或者在订阅到队列的时候就将auto_ack参数设置为 ...

  7. 基于rabbitMQ 消息延时队列方案 模拟电商超时未支付订单处理场景

    前言 传统处理超时订单 采取定时任务轮训数据库订单,并且批量处理.其弊端也是显而易见的:对服务器.数据库性会有很大的要求,并且当处理大量订单起来会很力不从心,而且实时性也不是特别好 当然传统的手法还可 ...

  8. SpringBoot | 第三十八章:基于RabbitMQ实现消息延迟队列方案

    前言 前段时间在编写通用的消息通知服务时,由于需要实现类似通知失败时,需要延后几分钟再次进行发送,进行多次尝试后,进入定时发送机制.此机制,在原先对接银联支付时,银联的异步通知也是类似的,在第一次通知 ...

  9. 【mq读书笔记】消息消费队列和索引文件的更新

    ConsumeQueue,IndexFile需要及时更新,否则无法及时被消费,根据消息属性查找消息也会出现较大延迟. mq通过开启一个线程ReputMessageService来准时转发commitL ...

随机推荐

  1. iOS动画效果合集、飞吧企鹅游戏、换肤方案、画板、文字效果等源码

    iOS精选源码 动画知识运用及常见动画效果收集 3D卡片拖拽卡片叠加卡片 iFIERO - FLYING PENGUIN 飞吧企鹅SpriteKit游戏(源码) Swift封装的空数据提醒界面Empt ...

  2. IDEA+selenium3+火狐/谷歌驱动 JAVA初步环境搭建 笔记

    0 环境 系统环境:win7 selenium驱动 谷歌浏览器以及驱动 火狐浏览器以及驱动 1 驱动地址的下载 1.1 selenium jar包 https://www.seleniumhq.org ...

  3. Servlet的Cookie对象

    Cookie的介绍:Cookie 定义:Cookie 用于浏览器端的数据存储,解决了不同请求之间需要数据共享的问题.例如,可以将用户的登录信息接收并设置为Cookie,对其进行相关操作以使得用户在特定 ...

  4. Windows 10操作系统针对不同环境下的安装方法

    一.电脑系统能正常运行 1.解压win10镜像文件 到电脑的非系统分区,运行setup安装文件 2.点击setup应用程序,准备安装 3.准备安装 4.等待安装过程结束,重启即可. 二.光盘安装 1. ...

  5. python与正则不得不说的故事

    今日所得 正则表达式 re模块 正则表达式:字符 元字符 匹配内容 . 匹配除换行符以外的任意字符 \w 匹配字母或数字或下划线 \s 匹配任意的空白符 \d 匹配数字 \n 匹配一个换行符 \t 匹 ...

  6. VDMA搭建视频通路总结

    全局观查,对整个工程的搭建的关键是要保证PL部分搭建成功,PS部分搭建成功,而且两者配合的很好. 我理解的PL部分涉及到模块的组合以及模块或者IP之间的逻辑的整理,PL部分困扰我比较久的是自动生成的w ...

  7. 吴裕雄--天生自然Android开发学习:下载安装android stuio集成开发工具

    下载链接: https://developer.android.google.cn/index.html

  8. python爬虫心得(第一天)

    爬虫是什么? 我个人觉得用简单通俗的话来说就是在浏览网页的过程中将有价值的信息下载到本地硬盘或者是储存到数据库中的行为. 爬虫的基础认知 可以参考此链接:https://www.imooc.com/a ...

  9. caffe之mac下环境搭建

    参考 http://www.linuxidc.com/Linux/2016-09/135026.html 1. 安装brew,也叫homebrew,mac下类似于ubuntu的apt-get功能 cu ...

  10. Spring Boot 之 Redis详解

    Redis是目前业界使用最广泛的内存数据存储. Redis支持丰富的数据结构,同时支持数据持久化. Redis还提供一些类数据库的特性,比如事务,HA,主从库. REmote DIctionary S ...