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 相关文章推荐
写js时遇到的一些小问题
Dec 06 Javascript
javascript中检测变量的类型的代码
Dec 28 Javascript
jquery中的工具使用方法$.isFunction, $.isArray(), $.isWindow()
Aug 09 Javascript
PHP+MySQL+jQuery随意拖动层并即时保存拖动位置实例讲解
Oct 09 Javascript
jQuery.trim() 函数及trim()用法详解
Oct 26 Javascript
如何利用AngularJS打造一款简单Web应用
Dec 05 Javascript
JS如何判断是否为ie浏览器的方法(包括IE10、IE11在内)
Dec 13 Javascript
Node.js实用代码段之正确拼接Buffer
Mar 17 Javascript
Knockoutjs 学习系列(二)花式捆绑
Jun 07 Javascript
使用InstantClick.js让页面提前加载200ms
Sep 12 Javascript
React为 Vue 引入容器组件和展示组件的教程详解
May 03 Javascript
学习node.js 断言的使用详解
Mar 18 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 file_put_contents()功能函数(集成了fopen、fwrite、fclose)
2011/05/24 PHP
遭遇php的in_array低性能问题
2013/09/17 PHP
php检测useragent版本示例
2014/03/24 PHP
PHP curl CURLOPT_RETURNTRANSFER参数的作用使用实例
2015/02/07 PHP
Laravel学习教程之View模块详解
2017/09/18 PHP
js可突破windows弹退效果代码
2008/08/09 Javascript
JQuery+CSS提示框实现思路及代码(纯手工打造)
2013/05/07 Javascript
js去空格技巧分别去字符串前后、左右空格
2013/10/21 Javascript
根据表格中的某一列进行排序的javascript代码
2013/11/29 Javascript
jquery validate添加自定义验证规则(验证邮箱 邮政编码)
2013/12/04 Javascript
基于js与flash实现的网站flv视频播放插件代码
2014/10/14 Javascript
Jquery中offset()和position()的区别分析
2015/02/05 Javascript
angularJS 中$attrs方法使用指南
2015/02/09 Javascript
JS检测是否可以访问公网服务器功能代码
2017/06/19 Javascript
angular或者js怎么确定选中ul中的哪几个li
2017/08/16 Javascript
Javascript查看大图功能代码实现
2020/05/07 Javascript
Python使用scrapy采集时伪装成HTTP/1.1的方法
2015/04/08 Python
简单分析Python中用fork()函数生成的子进程
2015/05/04 Python
Python封装shell命令实例分析
2015/05/05 Python
python绘图方法实例入门
2015/05/19 Python
Python中static相关知识小结
2018/01/02 Python
Python iter()函数用法实例分析
2018/03/17 Python
Django操作session 的方法
2020/03/09 Python
Python hashlib和hmac模块使用方法解析
2020/12/08 Python
HTML5 canvas基本绘图之图形组合
2016/06/27 HTML / CSS
结构工程研究生求职信
2013/10/13 职场文书
家庭教育先进个人事迹材料
2014/01/24 职场文书
年度献血先进个人事迹材料
2014/02/14 职场文书
2014春晚主持词
2014/03/25 职场文书
表扬稿格式范文
2015/01/16 职场文书
2015年幼儿园教研活动总结
2015/03/25 职场文书
小学中队活动总结
2015/05/11 职场文书
辩论会主持词
2015/07/03 职场文书
想要创业,那么你做好准备了吗?
2019/07/01 职场文书
使用python求解迷宫问题的三种实现方法
2022/03/17 Python
springboot创建的web项目整合Quartz框架的项目实践
2022/06/21 Java/Android