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 相关文章推荐
腾讯的ip接口 方便获取当前用户的ip地理位置
Nov 25 Javascript
当前页禁止复制粘贴截屏代码小集
Jul 24 Javascript
js history对象简单实现返回和前进
Oct 30 Javascript
超级好用的jQuery圆角插件 Corner速成
Aug 31 Javascript
Angular实现form自动布局
Jan 28 Javascript
jQuery实现点击任意位置弹出层外关闭弹出层效果
Oct 19 Javascript
javascript 中null和undefined区分和比较
Apr 19 Javascript
MUI实现上拉加载和下拉刷新效果
Jun 30 Javascript
Vue响应式原理深入解析及注意事项
Dec 11 Javascript
利用node实现一个批量重命名文件的函数
Dec 21 Javascript
JavaScript 类的封装操作示例详解
May 16 Javascript
vuex Module将 store 分割成模块的操作
Dec 07 Vue.js
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
使用Limit参数优化MySQL查询的方法
2008/11/12 PHP
php下通过IP获取地理位置的代码(小偷程序)
2011/06/09 PHP
PHP+MySQL删除操作实例
2015/01/21 PHP
PHP版本常用的排序算法汇总
2015/12/20 PHP
JS判断字符串长度的5个方法(区分中文和英文)
2014/03/18 Javascript
浅谈Javascript中匀速运动的停止条件
2014/12/19 Javascript
js实现Select下拉框具有输入功能的方法
2015/02/06 Javascript
jQuery中 attr() 方法使用小结
2015/05/03 Javascript
异步安全加载javascript文件的方法
2015/07/21 Javascript
javascript实现简单的页面右下角提示信息框
2015/07/31 Javascript
javascript中对变量类型的判断方法
2015/08/09 Javascript
详解JavaScript对象类型
2016/06/16 Javascript
JavaScript性能优化总结之加载与执行
2016/08/11 Javascript
AngularJS验证信息框架的封装插件用法【w5cValidator扩展插件】
2016/11/03 Javascript
Ajax高级笔记 JavaScript高级程序设计笔记
2017/06/22 Javascript
细说webpack源码之compile流程-rules参数处理技巧(2)
2017/12/26 Javascript
jQuery+CSS实现的table表格行列转置功能示例
2018/01/08 jQuery
vue-router命名视图的使用讲解
2019/01/19 Javascript
vue中keep-alive组件的入门使用教程
2019/06/06 Javascript
微信小程序跨页面数据传递事件响应实现过程解析
2019/12/19 Javascript
Python去掉字符串中空格的方法
2014/03/11 Python
浅谈DataFrame和SparkSql取值误区
2018/06/09 Python
Python大数据之网络爬虫的post请求、get请求区别实例分析
2019/11/16 Python
使用Python操作ArangoDB的方法步骤
2020/02/02 Python
一款基于css3的列表toggle特效实例教程
2015/01/04 HTML / CSS
html5文本内容_动力节点Java学院整理
2017/07/11 HTML / CSS
FOREO官方网站:LUNA露娜洁面仪
2016/11/28 全球购物
世界顶级足球门票网站:Live Football Tickets
2017/10/14 全球购物
国际贸易专业个人鉴定
2014/02/22 职场文书
创建精神文明单位实施方案
2014/03/08 职场文书
护士自我鉴定总结
2014/03/24 职场文书
授权委托书格式模板
2014/04/03 职场文书
平安工地建设方案
2014/05/06 职场文书
2015年机关纠风工作总结
2015/05/15 职场文书
创作书写之导游词实用技巧分享(干货)
2019/12/20 职场文书
Mysql官方性能测试工具mysqlslap的使用简介
2021/05/21 MySQL