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 相关文章推荐
基于Asp.net与Javascript控制的日期控件
May 22 Javascript
jquery如何把参数列严格转换成数组实现思路
Apr 01 Javascript
深入了解javascript中的prototype与继承
Apr 14 Javascript
cookie 最近浏览记录(中文escape转码)具体实现
Jun 08 Javascript
jQuery中not()方法用法实例
Jan 06 Javascript
浅谈js算法和流程控制
Dec 29 Javascript
JS实现简单抖动效果
Jun 01 Javascript
微信小程序实现顶部选项卡(swiper)
Jun 19 Javascript
Vue2.0 slot分发内容与props验证的方法
Dec 12 Javascript
vue-cli 首屏加载优化问题
Nov 06 Javascript
jQuery中实现text()的方法
Apr 04 jQuery
TS 类型兼容教程示例详解
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
粗略计算在线时间,bug:ip相同
2006/12/09 PHP
第五章 php数组操作
2011/12/30 PHP
关于URL最大长度限制的相关资料查证
2014/12/23 PHP
Laravel5中防止XSS跨站攻击的方法
2016/10/10 PHP
php中namespace及use用法分析
2016/12/06 PHP
php实现留言板功能
2017/03/05 PHP
javascript 树控件 比较好用
2009/06/11 Javascript
Javascript在IE下设置innerHTML时出现未知的运行时错误的解决方法
2011/01/12 Javascript
js jquery验证银行卡号信息正则学习
2013/01/21 Javascript
javascript中的=等号个数问题两个跟三个有什么区别
2013/10/23 Javascript
javascript函数式编程实例分析
2015/04/25 Javascript
学习JavaScript设计模式(策略模式)
2015/11/26 Javascript
AngularJS内建服务$location及其功能详解
2016/07/01 Javascript
vue的props实现子组件随父组件一起变化
2016/10/27 Javascript
JavaScript获取select中text值的方法
2017/02/13 Javascript
Angular 4依赖注入学习教程之FactoryProvider配置依赖对象(五)
2017/06/04 Javascript
Angular2 组件交互实例详解
2017/08/24 Javascript
微信小程序-getUserInfo回调的实例详解
2017/10/27 Javascript
jQuery实现带右侧索引功能的通讯录示例【附源码下载】
2018/04/17 jQuery
使用Vue的slot插槽分发父组件内容实现高度复用、更加灵活的组件(推荐)
2018/05/01 Javascript
layui 监听表格复选框选中值的方法
2018/08/15 Javascript
react高阶组件添加和删除props
2019/04/26 Javascript
详解JavaScript 高阶函数
2020/09/14 Javascript
jenkins自动构建发布vue项目的方法步骤
2021/01/04 Vue.js
Python和JavaScript间代码转换的4个工具
2016/02/22 Python
python 定时任务去检测服务器端口是否通的实例
2019/01/26 Python
pytorch之inception_v3的实现案例
2020/01/06 Python
Python多线程Threading、子线程与守护线程实例详解
2020/03/24 Python
HTML5离线缓存在tomcat下部署可实现图片flash等离线浏览
2012/12/13 HTML / CSS
美体小铺波兰官方网站:The Body Shop波兰
2019/09/03 全球购物
详解如何解决使用JSON.stringify时遇到的循环引用问题
2021/03/23 Javascript
生产部经理岗位职责
2013/12/16 职场文书
弘扬焦裕禄精神践行三严三实心得体会
2014/10/13 职场文书
领导干部作风建设总结
2014/10/23 职场文书
综合实践活动报告
2015/02/05 职场文书
党员学习中国梦心得体会
2016/01/05 职场文书