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 相关文章推荐
javascript实现unicode和字符的互相转换
Jul 18 Javascript
基于jQuery的一个扩展form序列化到json对象
Dec 09 Javascript
JavaScript 类型的包装对象(Typed Wrappers)
Oct 27 Javascript
用js实现table单元格高宽调整,兼容合并单元格(兼容IE6、7、8、FF)实例
Jun 25 Javascript
jQuery使用$.ajax进行异步刷新的方法(附demo下载)
Dec 04 Javascript
JavaScript浏览器对象模型BOM(BrowserObjectModel)实例详解
Nov 29 Javascript
javascript深拷贝和浅拷贝详解
Feb 14 Javascript
vue动态删除从数据库倒入列表的某一条方法
Sep 29 Javascript
vue微信分享的实现(在当前页面分享其他页面)
Apr 16 Javascript
vuex实现像调用模板方法一样调用Mutations方法
Nov 06 Javascript
js实现内置计时器
Dec 16 Javascript
vue制作toast组件npm包示例代码
Oct 29 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 object转数组示例
2014/01/15 PHP
关于php支持的协议与封装协议总结(推荐)
2017/11/17 PHP
PHP递归的三种常用方式
2019/02/28 PHP
在IE 浏览器中使用 jquery的fadeIn() 效果 英文字符字体加粗
2011/06/02 Javascript
js修改table中Td的值(定义td的双击事件)
2013/01/10 Javascript
JS+CSS实现Li列表隔行换色效果的方法
2015/02/16 Javascript
浅谈JavaScript异常处理语句
2015/06/26 Javascript
四种参数传递的形式——URL,超链接,js,form表单
2015/07/24 Javascript
学习JavaScript设计模式(多态)
2015/11/25 Javascript
jquery实现定时自动轮播特效
2015/12/10 Javascript
TypeScript Type Innference(类型判断)
2016/03/10 Javascript
js获取隐藏元素宽高的实现方法
2016/05/19 Javascript
js图片上传前预览功能(兼容所有浏览器)
2016/08/24 Javascript
前端框架Vue.js构建大型应用浅析
2016/09/12 Javascript
JS button按钮实现submit按钮提交效果
2016/11/01 Javascript
js与jquery分别实现tab标签页功能的方法
2016/11/18 Javascript
jQuery层级选择器_动力节点节点Java学院整理
2017/07/04 jQuery
微信小程序支付PHP代码
2018/08/23 Javascript
webpack+vue-cil 中proxyTable配置接口地址代理操作
2020/07/18 Javascript
JS如何生成动态列表
2020/09/22 Javascript
tensorflow实现softma识别MNIST
2018/03/12 Python
python浪漫表白源码
2019/04/05 Python
完美解决python3.7 pip升级 拒绝访问问题
2019/07/12 Python
用 Python 制作地球仪的方法
2020/04/24 Python
使用Pycharm在运行过程中,查看每个变量的操作(show variables)
2020/06/08 Python
Python存储读取HDF5文件代码解析
2020/11/25 Python
matplotlib 画动态图以及plt.ion()和plt.ioff()的使用详解
2021/01/05 Python
业务主管岗位职责
2013/11/20 职场文书
小学中秋节活动方案
2014/02/06 职场文书
乡镇纠风工作实施方案
2014/03/22 职场文书
网站美工岗位职责
2014/04/02 职场文书
公司授权委托书格式样本
2014/10/01 职场文书
计划生育工作汇报
2014/10/28 职场文书
支行行长岗位职责
2015/02/15 职场文书
python三子棋游戏
2022/05/04 Python
详解SQL报错盲注
2022/07/23 SQL Server