vue从零实现一个消息通知组件的方法详解


Posted in Javascript onMarch 16, 2020

本文实例讲述了vue从零实现一个消息通知组件的方法。分享给大家供大家参考,具体如下:

利用vue从零实现一个消息通知组件

平时,我们肯定用过类似element-ui,antd等一些UI框架,感受它们带给我们的便利。但当我们的需求或者设计这些框架内置的相差太大,用起来,就会觉得特别别扭,这时候,就有必要自己来重新造轮子。

重新造轮子,有几个好处,1.所有代码都是服务你的业务,没有太多用不上的东西。2.代码是由自己维护,而不是第三方,方便维护。3.提升自己的视野,让自己站在更高的角度来看问题。

好了,那话不多说,开始我们的组件开发吧!

文件目录的组件

工欲善其事,必先利其器,要想实现一个组件,一个好的目录结构,即可以划分职责,不同模块处理不同的逻辑!

我的目录结果是这样的:
vue从零实现一个消息通知组件的方法详解

接下来,我们依次对notification.vue, notify.js, index.js三个文件作介绍。

notification.vue

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: '关闭'
  }
 }
}
</script>
<style lang="less" scoped>
.fade-enter-active, .fade-leave-active{
 transition: opacity 1s;
}
.fade-enter, .fade-leave-to{
 opacity: 0;
}
.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;
 &__content{
  padding: 0;
 }
 &__btn{
  color: #ff4081;
  padding-left: 24px;
  margin-left: auto;
  cursor: pointer;
 }
}
</style>

notify.js

notify.js是一个处理消息通知组件的逻辑部分,其主要作用是暴露一个notify的方法出去。代码如下:

import Vue from 'vue'
import Notification from './notification'

const NotificationConstructor = Vue.extend(Notification)

const instances = []
let seed = 1
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,
  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 || 3000)
   },
   clearTimer() {
    if (this.timer) {
     clearTimeout(this.timer)
    }
   },
   handleClose() {
    this.visible = false
    document.body.removeChild(this.$el)
    removeInstance(this)
    this.$destroy(true)
   },
   handleAfterEnter() {
    // eslint-disable-next-line no-debugger
    this.height = this.$el.offsetHeight
   }
  }
 })

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

 // eslint-disable-next-line no-unused-vars
 let verticalOffset = 0

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

 verticalOffset += 16
 instance.verticalOffset = verticalOffset

 instances.push(instance)

 return instance
}

export default notify

index.js

index.js主要是对notification.vue组件实现注册,notify方法的挂载。代码如下:

import Notification from './notification'
import notify from './notify'

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

在main.js引入

import Notification from './components/notification'
Vue.use(Notification)

使用

this.$notify({
 content: 'Hello'
})

效果

vue从零实现一个消息通知组件的方法详解

希望本文所述对大家vue.js程序设计有所帮助。

Javascript 相关文章推荐
JavaScript URL参数读取改进版
Jan 16 Javascript
JavaScript 学习笔记(十四) 正则表达式
Jan 22 Javascript
JS中eval函数的使用示例
Jul 21 Javascript
Jquery简单分页实现方法
Jul 24 Javascript
JS实时弹出新消息提示框并有提示音响起的实现代码
Apr 20 Javascript
bootstrap table复杂操作代码
Nov 01 Javascript
JavaScript之Map和Set_动力节点Java学院整理
Jun 29 Javascript
Vue-router结合transition实现app前进后退动画切换效果的实例
Oct 11 Javascript
Vue中JS动画与Velocity.js的结合使用
Feb 13 Javascript
Vue组件通信的几种实现方法
Apr 25 Javascript
vue中使用百度脑图kityminder-core二次开发的实现
Sep 26 Javascript
《javascript设计模式》学习笔记五:Javascript面向对象程序设计工厂模式实例分析
Apr 08 Javascript
JavaScript实现动态留言板
Mar 16 #Javascript
vue中的双向数据绑定原理与常见操作技巧详解
Mar 16 #Javascript
js+canvas实现纸牌游戏
Mar 16 #Javascript
微信小程序利用button控制条件标签的变量问题
Mar 15 #Javascript
JS apply用法总结和使用场景实例分析
Mar 14 #Javascript
javascript事件循环event loop的简单模型解释与应用分析
Mar 14 #Javascript
原生js实现ajax请求和JSONP跨域请求操作示例
Mar 14 #Javascript
You might like
PHP开发者常犯的10个MySQL错误更正剖析
2012/01/30 PHP
php支付宝手机网页支付类实例
2015/03/04 PHP
PHP实现二叉树的深度优先与广度优先遍历方法
2015/09/28 PHP
详解PHP中的序列化、反序列化操作
2017/03/21 PHP
js以对象为索引的关联数组
2010/07/04 Javascript
分享27款非常棒的jQuery 表单插件
2011/03/28 Javascript
Javascript基础教程之JavaScript语法
2015/01/18 Javascript
.NET微信公众号开发之创建自定义菜单
2015/07/16 Javascript
微信小程序 textarea 组件详解及简单实例
2017/01/10 Javascript
JS设计模式之单例模式(一)
2017/09/29 Javascript
一次Webpack配置文件的分离实战记录
2018/11/30 Javascript
Vue.js 中的实用工具方法【推荐】
2019/07/04 Javascript
微信小程序实现录音功能
2019/11/22 Javascript
vue-video-player 解决微信自动全屏播放问题(横竖屏导致样式错乱问题)
2020/02/25 Javascript
Python正则抓取网易新闻的方法示例
2017/04/21 Python
Python 获取当前所在目录的方法详解
2017/08/02 Python
python实现redis三种cas事务操作
2017/12/19 Python
python 3.6 +pyMysql 操作mysql数据库(实例讲解)
2017/12/20 Python
Python 装饰器实现DRY(不重复代码)原则
2018/03/05 Python
Django框架会话技术实例分析【Cookie与Session】
2019/05/24 Python
Python类反射机制使用实例解析
2019/12/30 Python
如何把python项目部署到linux服务器
2020/08/26 Python
css3实现一个div设置多张背景图片及background-image属性实例演示
2017/08/10 HTML / CSS
CSS3弹性盒模型开发笔记(二)
2016/04/26 HTML / CSS
Html5 Canvas动画基础碰撞检测的实现
2018/12/06 HTML / CSS
戴森美国官网:Dyson美国
2016/09/11 全球购物
英智兴达软件测试笔试题
2016/10/12 面试题
节水倡议书范文
2014/04/15 职场文书
纪念九一八事变演讲稿:牢记九一八,屈辱怎能忘
2014/09/14 职场文书
2014年“向国旗敬礼”网上签名寄语活动方案
2014/09/27 职场文书
党的群众路线教育实践活动个人整改措施材料
2014/11/04 职场文书
2014年电教工作总结
2014/12/19 职场文书
离职信范本
2015/06/23 职场文书
2015教师节通讯稿
2015/07/20 职场文书
Python 如何将integer转化为罗马数(3999以内)
2021/06/05 Python
Minikube搭建Kubernetes集群
2022/03/31 Servers