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 相关文章推荐
event.keyCode键码值表 附只能输入特定的字符串代码
May 15 Javascript
JavaScript 字符串处理函数使用小结
Dec 02 Javascript
JQuery之拖拽插件实现代码
Apr 14 Javascript
javascript 循环调用示例介绍
Nov 20 Javascript
类似php的js数组的in_array函数自定义方法
Dec 27 Javascript
javascript实现汉字转拼音代码分享
Apr 20 Javascript
深入理解JavaScript中的call、apply、bind方法的区别
May 30 Javascript
基于JS实现9种不同的面包屑和分布式多步骤导航效果
Feb 21 Javascript
vue基于viewer实现的图片查看器功能
Apr 12 Javascript
Vue.extend实现挂载到实例上的方法
May 01 Javascript
浅谈 Webpack 如何处理图片(开发、打包、优化)
May 15 Javascript
Vue Render函数原理及代码实例解析
Jul 30 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学习之变量的使用
2011/05/29 PHP
php调用c接口无错版介绍
2014/03/11 PHP
朋友网关于QQ相关的PHP代码(研究QQ的绝佳资料)
2015/01/26 PHP
Yii2搭建后台并实现rbac权限控制完整实例教程
2016/04/28 PHP
PHP中递归的实现实例详解
2017/11/14 PHP
PHP 获取客户端 IP 地址的方法实例代码
2018/11/11 PHP
PHP Redis扩展无法加载的问题解决方法
2019/08/22 PHP
PHP实现的AES 128位加密算法示例
2019/09/16 PHP
javascript学习笔记(二十) 获得和设置元素的特性(属性)
2012/06/20 Javascript
jquery(hide方法)隐藏指定元素实例
2013/11/11 Javascript
JQuery控制radio选中和不选中方法总结
2015/04/15 Javascript
jQuery仿京东商城楼梯式导航定位菜单
2016/07/25 Javascript
基于Bootstrap框架实现图片切换
2017/03/10 Javascript
jQuery实现的简单在线计算器功能
2017/05/11 jQuery
vue动态配置模板 'component is'代码
2019/07/04 Javascript
浅谈javascript如何获取文件后缀名
2020/08/07 Javascript
React实现轮播效果
2020/08/25 Javascript
在vant中使用时间选择器和popup弹出层的操作
2020/11/04 Javascript
typescript编写微信小程序创建项目的方法
2021/01/29 Javascript
[08:08]DOTA2-DPC中国联赛2月28日Recap集锦
2021/03/11 DOTA
Python中实现的RC4算法
2015/02/14 Python
python 对dataframe下面的值进行大规模赋值方法
2018/06/09 Python
用Python实现大文本文件切割的方法
2019/01/12 Python
django 文件上传功能的相关实例代码(简单易懂)
2020/01/22 Python
Python图像处理库PIL的ImageEnhance模块使用介绍
2020/02/26 Python
Django contrib auth authenticate函数源码解析
2020/11/12 Python
如何通过jdbc调用存储过程
2012/04/19 面试题
党员违纪检讨书
2014/02/18 职场文书
《守株待兔》教学反思
2014/03/01 职场文书
法律进企业活动方案
2014/03/04 职场文书
抗洪救灾标语
2014/10/08 职场文书
开幕式邀请函
2015/01/31 职场文书
2015年底工作总结范文
2015/05/15 职场文书
小学教师教育随笔
2015/08/14 职场文书
Windows下用Nginx配置https服务器及反向代理的问题
2021/09/25 Servers
Winsows11性能如何? win11性能测评多核竟比Win10差了10%
2021/11/21 数码科技