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

Jacquelyn38
• 阅读 1267

前言

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

项目一览

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

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

源码

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

Notification.vue

<template>  
 <transition name="fade" @after-enter="handleAfterEnter">  
  <div class="notification" :style="style" v-show="visible">  
   <span class="notification__content">  
    {{content}}  
   </span>  
   <span class="notification__btn" @click="handleClose">{{btn}}</span>  
  </div>  
 </transition>  
</template>  
<script>  
export default {  
 name: 'Notification',  
 props: {  
  content: {  
   type: String,  
   required: true  
  },  
  btn: {  
   type: String,  
   default: 'close'  
  }  
 }  
}  
</script>  
<style lang="less" scoped>  
.fade-enter-active, .fade-leave-active{  
 transition: opacity 1s;  
}  
.fade-enter, .fade-leave-to{  
 opacity: 0;  
 transform: translateX(100px);  
}  
.notification{  
 display: flex;  
 background-color: #303030;  
 color: rgba(255, 255, 255, 1);  
 align-items: center;  
 padding: 20px;  
 position: fixed;  
 min-width: 280px;  
 box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0px 6px 10px 0px rgba(0, 0, 0, 0.3);  
 flex-wrap: wrap;  
 transition: all 0.3s;  
 border-radius:10px ;  
 &__content{  
  padding: 0;  
 }  
 &__btn{  
  color: #ff4081;  
  padding-left: 24px;  
  margin-left: auto;  
  cursor: pointer;  
 }  
}  
</style>  

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

notify.js

import Vue from "vue";  
import Notification from "./Notification.vue";  

const NotificationConstructor = Vue.extend(Notification);  

const instances = [];  
let seed = 1;  
// 消除Vue实例  
const removeInstance = (instance) => {  
  if (!instance) return;  
  const len = instances.length;  
  const index = instances.findIndex((ins) => instance.id === ins.id);  

  instances.splice(index, 1);  

  if (len <= 1) return;  
  const removeHeight = instance.height;  
  for (let i = index; i < len - 1; i++) {  
    instances[i].verticalOffset =  
      parseInt(instances[i].verticalOffset) - removeHeight - 16;  
  }  
};  

const notify = (options = {}) => {  
  if (Vue.prototype.$isServer) return;  
  // 获取vue实例  
  let instance = new NotificationConstructor({  
    propsData: options, // 这里是传进来一组props  
    data() {  
      return {  
        verticalOffset: 0,  
        timer: null,  
        visible: false,  
        height: 0,  
      };  
    },  
    computed: {  
      // 配置消息组件的位置  
      style() {  
        return {  
          position: "fixed",  
          right: "20px",  
          bottom: `${this.verticalOffset}px`,  
        };  
      }  
    },  
    mounted() {  
      this.createTimer();  
      this.$el.addEventListener("mouseenter", () => {  
        if (this.timer) {  
          this.clearTimer(this.timer);  
        }  
      });  
      this.$el.addEventListener("mouseleave", () => {  
        if (this.timer) {  
          this.clearTimer(this.timer);  
        }  
        this.createTimer();  
      });  
    },  
    updated() {  
      this.height = this.$el.offsetHeight;  
    },  
    beforeDestroy() {  
      this.clearTimer();  
    },  
    methods: {  
      // 创建计时器  
      createTimer() {  
        this.timer = setTimeout(() => {  
          this.visible = false;  
          document.body.removeChild(this.$el);  
          removeInstance(this);  
          this.$destroy();  
        }, options.timeout || 5000);  
      },  
      // 清除计时器  
      clearTimer() {  
        if (this.timer) {  
          clearTimeout(this.timer);  
        }  
      },  
      // 关闭消息弹窗  
      handleClose() {  
        this.visible = false;  
        document.body.removeChild(this.$el);  
        removeInstance(this);  
        this.$destroy(true);  
      },  
      // 过渡js钩子  
      handleAfterEnter() {  
        this.height = this.$el.offsetHeight;  
      },  
    },  
  });  

  const id = `notification_${seed++}`; // 动态生成唯一Id  
  instance.id = id;  
  // 生成vue中的$el  
  instance = instance.$mount();  
  // 将$el中的内容插入dom节点中去  
  document.body.appendChild(instance.$el);  
  instance.visible = true;  

  let verticalOffset = 0;  

  instances.forEach((item) => {  
    verticalOffset += item.$el.offsetHeight + 16;  
  });  

  verticalOffset += 16;  
  instance.verticalOffset = verticalOffset;  

  instances.push(instance);  

  return instance;  
};  

export default notify;  

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

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

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

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

<div id="app"></div>  
// 创建构造器  
var Profile = Vue.extend({  
  template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',  
  data: function () {  
    return {  
      firstName: 'Walter',  
      lastName: 'White',  
      alias: 'Heisenberg'  
    }  
  }  
})  
// 创建 Profile 实例,并挂载到一个元素上。  
new Profile().$mount('#app')  

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

官网的解释这样讲。

可以在 attribute 中声明 JavaScript 钩子

<transition  
  v-on:before-enter="beforeEnter"  
  v-on:enter="enter"  
  v-on:after-enter="afterEnter"  
  v-on:enter-cancelled="enterCancelled"  

  v-on:before-leave="beforeLeave"  
  v-on:leave="leave"  
  v-on:after-leave="afterLeave"  
  v-on:leave-cancelled="leaveCancelled"  
>  
  <!-- ... -->  
</transition>  
// ...  
methods: {  
  // --------  
  // 进入中  
  // --------  

  beforeEnter: function (el) {  
    // ...  
  },  
  // 当与 CSS 结合使用时  
  // 回调函数 done 是可选的  
  enter: function (el, done) {  
    // ...  
    done()  
  },  
  afterEnter: function (el) {  
    // ...  
  },  
  enterCancelled: function (el) {  
    // ...  
  },  

  // --------  
  // 离开时  
  // --------  

  beforeLeave: function (el) {  
    // ...  
  },  
  // 当与 CSS 结合使用时  
  // 回调函数 done 是可选的  
  leave: function (el, done) {  
    // ...  
    done()  
  },  
  afterLeave: function (el) {  
    // ...  
  },  
  // leaveCancelled 只用于 v-show 中  
  leaveCancelled: function (el) {  
    // ...  
  }  
}  

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

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

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

index.js

import Notification from "./Notification.vue";  
import notify from "./notify.js";  

export default (Vue) => {  
  Vue.component(Notification.name, Notification);  
  Vue.prototype.$notify = notify;  
};  

下面,我们将使用它。

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

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

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

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

结语

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

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

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

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

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
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
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
待兔 待兔
2个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
8个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这