vue从零实现一个消息通知组件的方法详解
本文实例讲述了vue从零实现一个消息通知组件的方法。分享给大家供大家参考,具体如下:
利用vue从零实现一个消息通知组件平时,我们肯定用过类似element-ui,antd等一些UI框架,感受它们带给我们的便利。但当我们的需求或者设计这些框架内置的相差太大,用起来,就会觉得特别别扭,这时候,就有必要自己来重新造轮子。
重新造轮子,有几个好处,1.所有代码都是服务你的业务,没有太多用不上的东西。2.代码是由自己维护,而不是第三方,方便维护。3.提升自己的视野,让自己站在更高的角度来看问题。
好了,那话不多说,开始我们的组件开发吧!
文件目录的组件工欲善其事,必先利其器,要想实现一个组件,一个好的目录结构,即可以划分职责,不同模块处理不同的逻辑!
我的目录结果是这样的:
接下来,我们依次对notification.vue, notify.js, index.js三个文件作介绍。
notification.vuenotification.vue是一个负责消息通知组件的视觉呈现,里面的逻辑很简单。
<template> <transition name='fade' @after-enter='handleAfterEnter'> <div : v-show='visible'> <span class='notification__content'> {{content}} </span> <span @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 = 1const 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 notifyindex.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.js程序设计有所帮助。
相关文章: