过年了,基于Vue做一个消息通知组件

前言

今天除夕,在这里祝大家新年快乐!!!今天在这个特别的日子里我们做一个消息通知组件,好,我们开始行动起来吧!!!

项目一览

效果很简单,就是这种的小卡片似的效果。

源码

我们先开始写UI页面,可自定义消息内容以及关闭按钮的样式。

Notification.vue

1<template> 2 <transition name="fade" @after-enter="handleAfterEnter"> 3 <div class="notification" :style="style" v-show="visible"> 4 <span class="notification__content"> 5 {{content}} 6 </span> 7 <span class="notification__btn" @click="handleClose">{{btn}}</span> 8 </div> 9 </transition> 10</template> 11<script> 12export default { 13 name: 'Notification', 14 props: { 15 content: { 16 type: String, 17 required: true 18 }, 19 btn: { 20 type: String, 21 default: 'close' 22 } 23 } 24} 25</script> 26<style lang="less" scoped> 27.fade-enter-active, .fade-leave-active{ 28 transition: opacity 1s; 29} 30.fade-enter, .fade-leave-to{ 31 opacity: 0; 32 transform: translateX(100px); 33} 34.notification{ 35 display: flex; 36 background-color: #303030; 37 color: rgba(255, 255, 255, 1); 38 align-items: center; 39 padding: 20px; 40 position: fixed; 41 min-width: 280px; 42 box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0px 6px 10px 0px rgba(0, 0, 0, 0.3); 43 flex-wrap: wrap; 44 transition: all 0.3s; 45 border-radius:10px ; 46 &__content{ 47 padding: 0; 48 } 49 &__btn{ 50 color: #ff4081; 51 padding-left: 24px; 52 margin-left: auto; 53 cursor: pointer; 54 } 55} 56</style> 57 58

写完基本的样式组件,我们该赋予其灵魂了。好,我们开始写最重要的逻辑。

notify.js

1import Vue from "vue"; 2import Notification from "./Notification.vue"; 3 4const NotificationConstructor = Vue.extend(Notification); 5 6const instances = []; 7let seed = 1; 8// 消除Vue实例 9const removeInstance = (instance) => { 10 if (!instance) return; 11 const len = instances.length; 12 const index = instances.findIndex((ins) => instance.id === ins.id); 13 14 instances.splice(index, 1); 15 16 if (len <= 1) return; 17 const removeHeight = instance.height; 18 for (let i = index; i < len - 1; i++) { 19 instances[i].verticalOffset = 20 parseInt(instances[i].verticalOffset) - removeHeight - 16; 21 } 22}; 23 24const notify = (options = {}) => { 25 if (Vue.prototype.$isServer) return; 26 // 获取vue实例 27 let instance = new NotificationConstructor({ 28 propsData: options, // 这里是传进来一组props 29 data() { 30 return { 31 verticalOffset: 0, 32 timer: null, 33 visible: false, 34 height: 0, 35 }; 36 }, 37 computed: { 38 // 配置消息组件的位置 39 style() { 40 return { 41 position: "fixed", 42 right: "20px", 43 bottom: `${this.verticalOffset}px`, 44 }; 45 } 46 }, 47 mounted() { 48 this.createTimer(); 49 this.$el.addEventListener("mouseenter", () => { 50 if (this.timer) { 51 this.clearTimer(this.timer); 52 } 53 }); 54 this.$el.addEventListener("mouseleave", () => { 55 if (this.timer) { 56 this.clearTimer(this.timer); 57 } 58 this.createTimer(); 59 }); 60 }, 61 updated() { 62 this.height = this.$el.offsetHeight; 63 }, 64 beforeDestroy() { 65 this.clearTimer(); 66 }, 67 methods: { 68 // 创建计时器 69 createTimer() { 70 this.timer = setTimeout(() => { 71 this.visible = false; 72 document.body.removeChild(this.$el); 73 removeInstance(this); 74 this.$destroy(); 75 }, options.timeout || 5000); 76 }, 77 // 清除计时器 78 clearTimer() { 79 if (this.timer) { 80 clearTimeout(this.timer); 81 } 82 }, 83 // 关闭消息弹窗 84 handleClose() { 85 this.visible = false; 86 document.body.removeChild(this.$el); 87 removeInstance(this); 88 this.$destroy(true); 89 }, 90 // 过渡js钩子 91 handleAfterEnter() { 92 this.height = this.$el.offsetHeight; 93 }, 94 }, 95 }); 96 97 const id = `notification_${seed++}`; // 动态生成唯一Id 98 instance.id = id; 99 // 生成vue中的$el 100 instance = instance.$mount(); 101 // 将$el中的内容插入dom节点中去 102 document.body.appendChild(instance.$el); 103 instance.visible = true; 104 105 let verticalOffset = 0; 106 107 instances.forEach((item) => { 108 verticalOffset += item.$el.offsetHeight + 16; 109 }); 110 111 verticalOffset += 16; 112 instance.verticalOffset = verticalOffset; 113 114 instances.push(instance); 115 116 return instance; 117}; 118 119export default notify; 120 121

当消息组件组高度超过浏览器显示区域的时候,消息组件会依次按顺序消失。

在这里,我们使用了Vue.extend(),在这里我们简单地介绍下,官网上是这样介绍的。

使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。

data 选项是特例,需要注意 - 在 Vue.extend() 中它必须是函数

1<div id="app"></div> 2
1// 创建构造器 2var Profile = Vue.extend({ 3 template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>', 4 data: function () { 5 return { 6 firstName: 'Walter', 7 lastName: 'White', 8 alias: 'Heisenberg' 9 } 10 } 11}) 12// 创建 Profile 实例,并挂载到一个元素上。 13new Profile().$mount('#app') 14

@after-enter="handleAfterEnter",看到这很多小伙伴会有疑问,其实这是Vue过渡组件中 JavaScript 钩子。

官网的解释这样讲。

可以在 attribute 中声明 JavaScript 钩子

1<transition 2 v-on:before-enter="beforeEnter" 3 v-on:enter="enter" 4 v-on:after-enter="afterEnter" 5 v-on:enter-cancelled="enterCancelled" 6 7 v-on:before-leave="beforeLeave" 8 v-on:leave="leave" 9 v-on:after-leave="afterLeave" 10 v-on:leave-cancelled="leaveCancelled" 11> 12 <!-- ... --> 13</transition> 14
1// ... 2methods: { 3 // -------- 4 // 进入中 5 // -------- 6 7 beforeEnter: function (el) { 8 // ... 9 }, 10 // 当与 CSS 结合使用时 11 // 回调函数 done 是可选的 12 enter: function (el, done) { 13 // ... 14 done() 15 }, 16 afterEnter: function (el) { 17 // ... 18 }, 19 enterCancelled: function (el) { 20 // ... 21 }, 22 23 // -------- 24 // 离开时 25 // -------- 26 27 beforeLeave: function (el) { 28 // ... 29 }, 30 // 当与 CSS 结合使用时 31 // 回调函数 done 是可选的 32 leave: function (el, done) { 33 // ... 34 done() 35 }, 36 afterLeave: function (el) { 37 // ... 38 }, 39 // leaveCancelled 只用于 v-show 中 40 leaveCancelled: function (el) { 41 // ... 42 } 43} 44

1.这些钩子函数可以结合 CSS transitions/animations 使用,也可以单独使用。2.当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则,它们将被同步调用,过渡会立即完成。3.推荐对于仅使用 JavaScript 过渡的元素添加 v-bind:css="false",Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。

详情解释可以查看官方文档

整理完UI组件与逻辑文件,下一步做得工作是将它们整合起来,通过Vue命令的方式直接使用。

index.js

1import Notification from "./Notification.vue"; 2import notify from "./notify.js"; 3 4export default (Vue) => { 5 Vue.component(Notification.name, Notification); 6 Vue.prototype.$notify = notify; 7}; 8

下面,我们将使用它。

main.js中引入index.js文件。

1import Notification from "../src/components/notification/index.js"; 2Vue.use(Notification); 3

然后,你在相应的组件中这样调用它即可。

1this.$notify({ 2 content: "Hello World", // 消息内容 3 btn: "关闭" // 关闭按钮内容 4}); 5

结语

谢谢大家阅读,希望没有浪费大家的时间。新的一年即将来临,2021年祝大家工作顺利,平平安安。

本文转转自微信公众号前端历劫之路原创https://mp.weixin.qq.com/s/SS50RmN0bo9F3P3zOSvZiA,如有侵权,请联系删除。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )