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 相关文章推荐
密码强度检测效果实现原理与代码
Jan 04 Javascript
九种js弹出对话框的方法总结
Mar 12 Javascript
js禁止document element对象选中文本实现代码
Mar 21 Javascript
location对象的属性和方法应用(解析URL)
Apr 12 Javascript
表单序列化与jq中的serialize使用示例
Feb 21 Javascript
ajax请求乱码的解决方法(中文乱码)
Apr 10 Javascript
关闭浏览器窗口弹出提示框并且可以控制其失效
Apr 15 Javascript
javaScript年份下拉列表框内容为当前年份及前后50年
May 28 Javascript
js实现音频控制进度条功能
Apr 01 Javascript
javaScript实现复选框全选反选事件详解
Nov 20 Javascript
Node Puppeteer图像识别实现百度指数爬虫的示例
Feb 22 Javascript
微信小程序实现蓝牙打印
Sep 23 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实现Ftp用户的在线管理的代码
2007/03/06 PHP
PHP中__FILE__、dirname与basename用法实例分析
2014/12/01 PHP
php查看网页源代码的方法
2015/03/13 PHP
php实现图片转换成ASCII码的方法
2015/04/03 PHP
PHP创建自己的Composer包方法
2018/04/09 PHP
JavaScript 面向对象之命名空间
2010/05/04 Javascript
jquery弹出框的用法示例(2)
2013/08/26 Javascript
JS中类或对象的定义说明
2014/03/10 Javascript
JavaScript判断DIV内容是否为空的方法
2016/01/29 Javascript
教你用javascript实现随机标签云效果_附代码
2016/03/16 Javascript
JavaScript创建对象的七种方式(推荐)
2017/06/26 Javascript
使用canvas进行图像编辑的实例
2017/08/29 Javascript
form表单数据封装成json格式并提交给服务器的实现方法
2017/12/14 Javascript
jQuery+ajax实现动态添加表格tr td功能示例
2018/04/23 jQuery
使用python编写批量卸载手机中安装的android应用脚本
2014/07/21 Python
用Python制作检测Linux运行信息的工具的教程
2015/04/01 Python
python检测某个变量是否有定义的方法
2015/05/20 Python
Python实现高效求解素数代码实例
2015/06/30 Python
Python生成随机验证码的两种方法
2015/12/22 Python
利用selenium 3.7和python3添加cookie模拟登陆的实现
2017/11/20 Python
python3.4实现邮件发送功能
2018/05/28 Python
python selenium自动上传有赞单号的操作方法
2018/07/05 Python
对TensorFlow的assign赋值用法详解
2018/07/30 Python
详解Matplotlib绘图之属性设置
2019/08/23 Python
使用python无账号无限制获取企查查信息的实例代码
2020/04/17 Python
Ubuntu 20.04安装Pycharm2020.2及锁定到任务栏的问题(小白级操作)
2020/10/29 Python
python 如何在测试中使用 Mock
2021/03/01 Python
CSS3 重置iphone浏览器按钮input,select等表单元素的默认样式
2014/10/11 HTML / CSS
如何整合JQuery和Prototype
2014/01/31 面试题
临床医学专业毕业生的自我评价
2013/10/17 职场文书
毕业生优秀推荐信
2013/11/26 职场文书
校园餐饮创业计划书
2014/01/10 职场文书
飞机制造技术专业求职信
2014/07/27 职场文书
食品委托检验协议书范本
2014/09/12 职场文书
2015年教师自我评价范文
2015/03/04 职场文书
nginx 配置指令之location使用详解
2022/05/25 Servers