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 相关文章推荐
List the Codec Files on a Computer
Jun 11 Javascript
jQuery实现的类flash菜单效果代码
May 17 Javascript
JavaScript实现弹出子窗口并传值给父窗口
Dec 18 Javascript
javascript实现多级联动下拉菜单的方法
Feb 06 Javascript
jQuery实现根据类型自动显示和隐藏表单
Mar 18 Javascript
基于HTML模板和JSON数据的JavaScript交互(移动端)
Apr 06 Javascript
jQuery轻松实现无缝轮播效果
Mar 22 jQuery
详解基于webpack搭建react运行环境
Jun 01 Javascript
浅谈vue.use()方法从源码到使用
May 12 Javascript
vue递归组件实战之简单树形控件实例代码
Aug 27 Javascript
处理JavaScript值为undefined的7个小技巧
Jul 28 Javascript
JavaScript实现贪吃蛇游戏
Jun 16 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
咖啡店都有些什么常规豆子呢?有什么风味在里面
2021/03/04 咖啡文化
关于php连接mssql:pdo odbc sql server
2011/07/20 PHP
详解PHP用substr函数截取字符串中的某部分
2016/12/03 PHP
PHP使用Redis替代文件存储Session的方法
2017/02/15 PHP
用js实现上传图片前的预览(TX的面试题)
2007/08/14 Javascript
网页中返回顶部代码(多种方法)另附注释说明
2013/04/24 Javascript
javascript在子页面中函数无法调试问题解决方法
2014/01/17 Javascript
jQuery+ajax实现无刷新级联菜单示例
2015/05/21 Javascript
JQuery+CSS实现图片上放置按钮的方法
2015/05/29 Javascript
js实现类似菜单风格的TAB选项卡效果代码
2015/08/28 Javascript
js实现将选中内容分享到新浪或腾讯微博
2015/12/16 Javascript
js利用正则表达式检验输入内容是否为网址
2016/07/05 Javascript
在Docker快速部署Node.js应用的详细步骤
2016/09/02 Javascript
Vue中建立全局引用或者全局命令的方法
2017/08/21 Javascript
vue 巧用过渡效果(小结)
2018/09/22 Javascript
基于vue2.0实现仿百度前端分页效果附实现代码
2018/10/30 Javascript
微信浏览器下拉黑边解决方案 wScroollFix
2020/01/21 Javascript
在Python的Django框架中加载模版的方法
2015/07/16 Python
Python列表list内建函数用法实例分析【insert、remove、index、pop等】
2017/07/24 Python
python实现手机通讯录搜索功能
2018/02/22 Python
PyQt5每天必学之事件与信号
2018/04/20 Python
Python matplotlib绘制饼状图功能示例
2019/09/10 Python
PyTorch中topk函数的用法详解
2020/01/02 Python
中国包裹转运寄送国际服务:Famiboat
2019/07/24 全球购物
Perfume’s Club英国官网:购买香水和护肤品
2019/11/02 全球购物
房产销售经理职责
2013/12/20 职场文书
竞选村长演讲稿
2014/04/28 职场文书
自强之星事迹材料
2014/05/12 职场文书
公司经营目标责任书
2015/01/29 职场文书
电影小兵张嘎观后感
2015/06/03 职场文书
离职员工给领导和同事的感谢信
2015/11/03 职场文书
2016年暑假家长对孩子评语
2015/12/01 职场文书
机关干部作风整顿心得体会
2016/01/22 职场文书
导游词之清晏园
2019/11/22 职场文书
关于Mybatis中SQL节点的深入解析
2022/03/19 Java/Android
volatile保证可见性及重排序方法
2022/08/05 Java/Android