Vue Snackbar 消息条队列显示,依次动画消失的实现
效果预览

思路
- 封装 Snackbar 组件;
- 在根路由页面下建立全局 Snackbar 控制器,统一管理 Snackbar;
- 通过事件通知全局 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 消息条队列显示,依次动画消失的实现的更多相关文章
- 前端基于VUE的v-charts的曲线显示
目录 前端基于VUE的v-charts的曲线显示 1. 应用背景 2. 分析数据生产者生成 3. 取出数据消费者 4. 前端显示 4.1 安装V-charts插件 4.2 引入veline曲线插件 4 ...
- vue 圆形进度条组件解析
项目简介 本组件是vue下的圆形进度条动画组件 自由可定制,几乎全部参数均可设置 源码简单清晰 面向人群 急于使用vue圆形进度条动画组件的同学.直接下载文件,拷贝代码即可运行. 喜欢看源码,希望了解 ...
- Android百度地图开发(五)公交线路详情搜索、多条线路显示
一.公交线路详情检索 获取公交线路的详情主要分来两步,1.获取公交线路的Uid,2.通过Uid获取公交线路详情. 1.获取公交线路的Uid: /* * 获得公交线路图的Uid,并且根据系Uid发起公交 ...
- 让TextView里面的文字逐个显示的动画效果实现(1)
最近使用TextView时想要实现里面的文字逐个显示的动画效果,就如同打字一样. 主要实现思想:新建一个TextView的派生类,先将要逐个显示的字符串保存变量 mOriginalStr 中,然后启动 ...
- HTML5效果:Canvas 实现圆形进度条并显示数字百分比
实现效果 1.首先创建html代码 <canvas id="canvas" width="500" height="500" styl ...
- RabbitMQ基础概念(消息、队列、交换机)
1.消息的确认 RabbitMQ需要对每一条发送的消息进行确认.消费者必须通过AMQP的basic.ack命令显式地向RabbitMQ发送一个确认,或者在订阅到队列的时候就将auto_ack参数设置为 ...
- 基于rabbitMQ 消息延时队列方案 模拟电商超时未支付订单处理场景
前言 传统处理超时订单 采取定时任务轮训数据库订单,并且批量处理.其弊端也是显而易见的:对服务器.数据库性会有很大的要求,并且当处理大量订单起来会很力不从心,而且实时性也不是特别好 当然传统的手法还可 ...
- SpringBoot | 第三十八章:基于RabbitMQ实现消息延迟队列方案
前言 前段时间在编写通用的消息通知服务时,由于需要实现类似通知失败时,需要延后几分钟再次进行发送,进行多次尝试后,进入定时发送机制.此机制,在原先对接银联支付时,银联的异步通知也是类似的,在第一次通知 ...
- 【mq读书笔记】消息消费队列和索引文件的更新
ConsumeQueue,IndexFile需要及时更新,否则无法及时被消费,根据消息属性查找消息也会出现较大延迟. mq通过开启一个线程ReputMessageService来准时转发commitL ...
随机推荐
- jQuery实现button按钮提交表单
在JSP页面中,通常使用button按钮提交表单数据,使用jQuery实现代码如下: <span style="font-family:Comic Sans MS;font-size: ...
- [LC] 250. Count Univalue Subtrees
Given a binary tree, count the number of uni-value subtrees. A Uni-value subtree means all nodes of ...
- 常用的SQL优化
转自:https://www.cnblogs.com/Cheney222/articles/5876382.html 一.优化 SQL 语句的一般步骤 1 通过 show status 命令了解各种 ...
- perf4j+logback配置 非spring 可使用注解
最近项目打算使用perf4j进行性能监控,由于项目没有使用spring,而又不想对代码入侵过高,打算使用注解的方式进行接入.perf4j采用AspectJ库实现AOP. 具体接入方法如下: logba ...
- htaccess 伪静态的规则
利用htaccess文件可以很好的进行站点伪静态,并且形成的目标地址与真正的静态页面几乎一模一样,如abc.html等,伪静态可以非常好的结合SEO来提高站点的排名,并且也能给人一种稳定的印象. 由于 ...
- 吴裕雄--天生自然python学习笔记:网页解析
抓取万水书苑网页中所有<a>标签中的超链接井显示. import requests from bs4 import BeautifulSoup url = 'http://www.wsbo ...
- quote|additives|Feel free to help| thick of |take in|soar|eternal|add up to|pull through| in reserve|
A quote for a piece of work is the price that someone says they will charge you to do the work. Alwa ...
- FastJson的学习之JSON互相转Map集合,List集合,JavaBean
https://blog.csdn.net/weixin_36910300/article/details/79182120 创建两个实体类 一个是部门类,一个是部门员工类 部门员工类 public ...
- Ionic3学习笔记(十)实现夜间模式功能
本文为原创文章,转载请标明出处 目录 创建主题样式 导入 variables.scss 创建 provider 创建 page 在 App 入口处应用主题 效果图 1. 创建主题样式 在 ./src/ ...
- HEALER
项目介绍: 专注是一款时间管理应用,可以帮你管理时间,制定计划,让你保持专注,从快节奏的当下抽离,进入另一个平和安静的时空,以获得更好的工作和学习效率. 主模块(专注):设置分类.专注时长.简介,点击 ...