前言
一直都覺得vue的插件生澀難懂,但是又很好奇,在看了幾篇文章,試著寫了寫之后覺得也沒那么難,本文主要實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Toast插件,方便遷移到不同的項(xiàng)目中,用來全局提示、警告一些信息。
概述:
在前端項(xiàng)目中,有時(shí)會(huì)需要通知、提示一些信息給用戶,尤其是在后臺(tái)系統(tǒng)中,操作的正確與否,都需要給與用戶一些信息。
1. 實(shí)例
在Vue組件的methods內(nèi),調(diào)用如下代碼
this.$toast({ content: "可自動(dòng)關(guān)閉", autoClose: true})在頁(yè)面的右側(cè)會(huì)出現(xiàn)一個(gè)Toast彈框,多次點(diǎn)擊時(shí),會(huì)依照順序進(jìn)行顯示,并且Toast可自動(dòng)關(guān)閉,具體效果如圖。

代碼地址:Github UI-Library
2. 原理
代碼結(jié)構(gòu)
將Toast插件分為兩個(gè)部分:
Toast方法
為了能夠通過this.$toast({...})調(diào)用Toast組件,須在Vue的prototype上添加一個(gè)方法,如下
let instances = []let initIndex = 0Vue.prototype.$toast = (options = {}) => { /* 創(chuàng)建一個(gè)Toast組件的實(shí)例 */ let instance = generateInstance(options) /* 將單個(gè)toast存入隊(duì)列中 */ instances.push(instance)}當(dāng)調(diào)用該方法時(shí),通過generateInstance創(chuàng)建一個(gè)Toast組件的實(shí)例,并將其放入instances,統(tǒng)一管理。
/* 構(gòu)造單個(gè)toast */const ToastConstructor = Vue.extend(Toast)const verticalOffset = 16function generateInstance(options) { // 利用ToastConstructor創(chuàng)建一個(gè)Toast的實(shí)例 let instance = new ToastConstructor({ propsData: options }).$mount(document.createElement('div')) if (typeof options.onClose === 'function') instance.onClose = options.onClose //計(jì)算instance verticalOffset let id = 'toast_' + initIndex++ instance.id = id // 初始化Toast在空間中的垂直偏移量 instance.verticalOffset = initVerticalOffset(instance.position) //監(jiān)聽組件close instance.$once('toastClose', function () { const curInstance = this // 當(dāng)Toast組件關(guān)閉時(shí),重新計(jì)算垂直方向的偏移量 updateVerticalOffset(curInstance) typeof curInstance.onClose === 'function' && curInstance.onClose() }) return instance;}generateInstance函數(shù)中,首先利用ToastConstructor構(gòu)造函數(shù)創(chuàng)建一個(gè)Toast組件的實(shí)例,并通過propsData傳入屬性值,同時(shí)通過$mount(document.createElement('div'))渲染該組件。
ToastConstructor是通過Vue.extend創(chuàng)造Toast組件的構(gòu)造函數(shù),關(guān)于這部分的具體原理,可以參考
基于Vue構(gòu)造器創(chuàng)建Form組件的通用解決方案。
/* 初始化每個(gè)toast對(duì)象在頁(yè)面中的垂直屬性 */function initVerticalOffset(position) { // 篩選同一方向的Toast組件 let typeInstances = instances.filter(item => item.position === position) // 計(jì)算偏移量 return typeInstances.reduce((sum, elem) => (elem.$el.offsetHeight + sum + verticalOffset), verticalOffset)}之后當(dāng)某個(gè)Toast關(guān)閉時(shí),需要更新所有Toast實(shí)例在頁(yè)面中偏移量
/* 更新每個(gè)toast對(duì)象在頁(yè)面中的垂直屬性 */function updateVerticalOffset(removeInstance) { let index = 0 let removeHeight = removeInstance.verticalOffset instances.find((elem, i) => { if (elem.id === removeInstance.id) index = i }) // 刪除關(guān)閉的Toast組件 instances.splice(index, 1) // 更新在刪除位置之后的組件的位置 for (; index < instances.length; ++index) { if (instances[index].position === removeInstance.position) { [instances[index].verticalOffset, removeHeight] = [removeHeight, instances[index].verticalOffset] } }}以上完成了Toast組件的創(chuàng)建、如何在頁(yè)面中初始化、更新的位置。
Toast組件
組件的功能比較簡(jiǎn)單,只需要展示信息,以及具備自動(dòng)關(guān)閉、手動(dòng)關(guān)閉兩個(gè)功能,屬性也要包括Toast的類型、位置、內(nèi)容等。
組件的生命周期
let instance = new ToastConstructor({ propsData: options}).$mount(document.createElement('div'))當(dāng)Toast組件$mount調(diào)用時(shí),會(huì)觸發(fā)mounted的生命周期
mounted() { // 掛載Toast在頁(yè)面中 document.body.appendChild(this.$el); // 需要自動(dòng)關(guān)閉時(shí),調(diào)用startTimer if (this.autoClose) this.startTimer();},beforeDestroy() { this.stopTimer(); this.$el.removeEventListener("transitionend", this.destroyElement);},destroyed() { // 注銷 this.$el.parentNode.removeChild(this.$el);}自動(dòng)關(guān)閉
需要自動(dòng)時(shí),就要在利用setTimeout完成該功能,并在注銷時(shí)clearTimeout掉,防止泄露。
startTimer() { if (this.duration > 0) { this.timer = setTimeout(() => { if (!this.closed) { this.close(); } }, this.duration); }},stopTimer() { if (this.timer) clearTimeout(this.timer);}3. 使用
進(jìn)一步將其封裝成Vue的插件
export default { install (Vue) { Vue.prototype.$toast = (options = {}) => {...} }}并且對(duì)所需要傳入的必需屬性,做處理異常處理
export default { install (Vue) { Vue.prototype.$toast = (options = {}) => {...} }}4. 總結(jié)
通過封裝一個(gè)Toast插件,提取不同業(yè)務(wù)之間公共的部分,減少業(yè)務(wù)的工作量。
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)武林網(wǎng)的支持。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注