vue從零實現一個訊息通知元件的方法詳解
阿新 • • 發佈:2020-03-17
本文例項講述了vue從零實現一個訊息通知元件的方法。分享給大家供大家參考,具體如下:
利用vue從零實現一個訊息通知元件
平時,我們肯定用過類似element-ui,antd等一些UI框架,感受它們帶給我們的便利。但當我們的需求或者設計這些框架內建的相差太大,用起來,就會覺得特別彆扭,這時候,就有必要自己來重新造輪子。
重新造輪子,有幾個好處,1.所有程式碼都是服務你的業務,沒有太多用不上的東西。2.程式碼是由自己維護,而不是第三方,方便維護。3.提升自己的視野,讓自己站在更高的角度來看問題。
好了,那話不多說,開始我們的元件開發吧!
檔案目錄的元件
工欲善其事,必先利其器,要想實現一個元件,一個好的目錄結構,即可以劃分職責,不同模組處理不同的邏輯!
我的目錄結果是這樣的:
接下來,我們依次對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,1); align-items: center; padding: 20px; position: fixed; min-width: 280px; box-shadow: 0 3px 5px -1px rgba(0,0.2),0px 6px 10px 0px rgba(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.js程式設計有所幫助。