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团队打造的javascript单元测试工具QUnit介绍
Feb 26 Javascript
jquery-tips悬浮提示插件分享
Jul 31 Javascript
学习JavaScript设计模式之代理模式
Jan 12 Javascript
1秒50万字!js实现关键词匹配
Aug 01 Javascript
JavaScript设置名字输入不合法的实现方法
May 23 Javascript
将angular.js项目整合到.net mvc中的方法详解
Jun 29 Javascript
JS实现遍历不规则多维数组的方法
Mar 21 Javascript
Vue项目分环境打包的实现步骤
Apr 02 Javascript
Vue全局分页组件的实现代码
Aug 10 Javascript
layui清空,重置表单数据的实例
Sep 12 Javascript
解决Vue项目打包后打开index.html页面显示空白以及图片路径错误的问题
Oct 25 Javascript
js实现石头剪刀布游戏
Oct 11 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实现文件上传二法
2006/10/09 PHP
php处理json时中文问题的解决方法
2011/04/12 PHP
PHP PDOStatement对象bindpram()、bindvalue()和bindcolumn之间的区别
2014/11/20 PHP
PHP+jQuery翻板抽奖功能实现
2015/10/19 PHP
Yii2框架引用bootstrap中日期插件yii2-date-picker的方法
2016/01/09 PHP
PHP 根据key 给二维数组分组
2016/12/09 PHP
yii框架结合charjs实现统计30天数据的方法
2020/04/04 PHP
基于php伪静态的实现方法解析
2020/07/31 PHP
当自定义数据属性为json格式字符串时jQuery的data api问题探讨
2013/02/18 Javascript
jquery 检测元素是否存在的实例代码
2013/11/19 Javascript
元素绑定click点击事件方法
2015/06/08 Javascript
node.js用fs.rename强制重命名或移动文件夹的方法
2017/12/27 Javascript
详解React开发必不可少的eslint配置
2018/02/05 Javascript
Vue路由钩子之afterEach beforeEach的区别详解
2018/07/15 Javascript
jQuery实现的隔行变色功能【案例】
2019/02/18 jQuery
WebSocket的简单介绍及应用
2019/05/23 Javascript
微信小程序 数据缓存实现方法详解
2019/08/26 Javascript
在layui.use 中自定义 function 的正确方法
2019/09/16 Javascript
[01:22:42]2014 DOTA2华西杯精英邀请赛 5 24 DK VS LGD
2014/05/26 DOTA
Python列表生成器的循环技巧分享
2015/03/06 Python
在Python的Flask框架中实现单元测试的教程
2015/04/20 Python
Python中Collections模块的Counter容器类使用教程
2016/05/31 Python
解决Shell执行python文件,传参空格引起的问题
2018/10/30 Python
用python给自己做一款小说阅读器过程详解
2019/07/11 Python
python os.path.isfile 的使用误区详解
2019/11/29 Python
Python面向对象原理与基础语法详解
2020/01/02 Python
Python基于codecs模块实现文件读写案例解析
2020/05/11 Python
浅谈django 重载str 方法
2020/05/19 Python
教师远程培训感言
2014/03/06 职场文书
商务英语广告词大全
2014/03/18 职场文书
乡镇综治宣传月活动总结
2014/07/02 职场文书
班级学习雷锋活动总结
2014/07/04 职场文书
夫妻忠诚协议范文
2014/11/16 职场文书
入党自传范文2015
2015/06/26 职场文书
Python 语言实现六大查找算法
2021/06/30 Python
PostgreSQL解析URL的方法
2021/08/02 PostgreSQL