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 相关文章推荐
JQuery 学习笔记 element属性控制
Jul 23 Javascript
一个简单的js动画效果代码
Jul 20 Javascript
ExtJS4 动态生成的grid导出为excel示例
May 02 Javascript
jQuery使用prepend()方法在元素前添加内容用法实例
Mar 26 Javascript
JavaScript 里的类数组对象
Apr 08 Javascript
js控制网页前进和后退的方法
Jun 08 Javascript
基于JavaScript如何实现私有成员的语法特征及私有成员的实现方式
Oct 28 Javascript
AngularJS中$interval的用法详解
Feb 02 Javascript
jQuery基于json与cookie实现购物车的方法
Apr 15 Javascript
pm2 部署 node的三种方法示例
Oct 20 Javascript
Vue.js实现双向数据绑定方法(表单自动赋值、表单自动取值)
Aug 27 Javascript
js实现按钮开关单机下拉菜单效果
Nov 22 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
web目录下不应该存在多余的程序(安全考虑)
2012/05/09 PHP
php数组编码转换示例详解
2014/03/11 PHP
CI框架网页缓存简单用法分析
2018/12/26 PHP
js 采用delete实现继承示例代码
2014/05/20 Javascript
JavaScript ParseFloat()方法
2015/12/18 Javascript
javascript单页面手势滑屏切换原理详解
2016/03/21 Javascript
很棒的js选项卡切换效果
2016/07/15 Javascript
微信小程序前端源码逻辑和工作流
2016/09/25 Javascript
bootstrap警告框使用方法解析
2017/01/13 Javascript
AngularJS页面传参的5种方式
2017/04/01 Javascript
jQuery实现动态给table赋值的方法示例
2017/07/04 jQuery
vue mint-ui学习笔记之picker的使用
2017/10/11 Javascript
vue模仿网易云音乐的单页面应用
2019/04/24 Javascript
使用Vue-cli3.0创建的项目 如何发布npm包
2019/10/10 Javascript
在vue中实现给每个页面顶部设置title
2020/07/29 Javascript
vue项目打包后请求地址错误/打包后跨域操作
2020/11/04 Javascript
[52:29]DOTA2上海特级锦标赛主赛事日 - 2 胜者组第一轮#3Secret VS OG第三局
2016/03/03 DOTA
Python检测生僻字的实现方法
2016/10/23 Python
django启动uwsgi报错的解决方法
2018/04/08 Python
python 判断矩阵中每行非零个数的方法
2019/01/26 Python
python制作填词游戏步骤详解
2019/05/05 Python
Django中自定义admin Xadmin的实现代码
2019/08/09 Python
Django 设置多环境配置文件载入问题
2020/02/25 Python
pycharm 对代码做静态检查操作
2020/06/09 Python
Python selenium爬取微信公众号文章代码详解
2020/08/12 Python
Python下载网易云歌单歌曲的示例代码
2020/08/12 Python
Maxpeedingrods美国:高性能汽车零件
2020/02/14 全球购物
Tomcat的缺省是多少,怎么修改
2014/04/09 面试题
制药工程专业毕业生推荐信
2013/12/24 职场文书
创业计划书中包含的9个方面
2013/12/26 职场文书
培训心得体会
2013/12/29 职场文书
股东协议书
2014/04/14 职场文书
淘宝店策划方案
2014/06/07 职场文书
Python OpenCV 彩色与灰度图像的转换实现
2021/06/05 Python
关于HTML编码导致的乱码问题
2021/09/04 HTML / CSS
MySQL GTID复制的具体使用
2022/05/20 MySQL