從零開始實現Vue簡單的Toast插件

概述:

在前端項目中,有時會須要通知、提示一些信息給用戶,尤爲是在後臺系統中,操做的正確與否,都須要給與用戶一些信息。

1. 實例

在Vue組件的methods內,調用以下代碼
`this``.$toast({`=
`content:` `"可自動關閉"``,`
`autoClose:` `true`
`})`

在頁面的右側會出現一個Toast彈框,屢次點擊時,會依照順序進行顯示,而且Toast可自動關閉,具體效果如圖。前端

代碼地址:Github UI-Librarygit

2. 原理

代碼結構github

將Toast插件分爲兩個部分:
  • Toast組件自己,包含自己的dom結構以及data,並在其生命週期完成在頁面中的掛載與銷燬;
  • 在組件外構建一層代理並提供相關方法用於調用、並控制多個Toast在頁面中顯示的順序。

Toast方法app

爲了可以經過 this.$toast({...})調用Toast組件,須在Vue的prototype上添加一個方法,以下
`let instances = []`
`let initIndex = 0`
`Vue.prototype.$toast = (options = {}) => {`
`/* 建立一個Toast組件的實例 */`
`let instance = generateInstance(options)`
`/* 將單個toast存入隊列中 */`
`instances.push(instance)`
`}`
當調用該方法時,經過generateInstance建立一個Toast組件的實例,並將其放入instances,統一管理。
`/* 構造單個toast */`
`const ToastConstructor = Vue.extend(Toast)`
`const verticalOffset = 16`
`function` `generateInstance(options) {`
`// 利用ToastConstructor建立一個Toast的實例`
`let instance =` `new` `ToastConstructor({`
`propsData: options`
`}).$mount(document.createElement(``'div'``))`
`if` `(``typeof` `options.onClose ===` `'function'``) instance.onClose = options.onClose`
`//計算instance verticalOffset`
`let id =` `'toast_'` `+ initIndex++`
instance.id = id`
`// 初始化Toast在空間中的垂直偏移量`
`instance.verticalOffset = initVerticalOffset(instance.position)`
`//監聽組件close`
`instance.$once(``'toastClose'``,` `function` `() {`
`const curInstance =` `this`
`// 當Toast組件關閉時,從新計算垂直方向的偏移量`
`updateVerticalOffset(curInstance)`
`typeof` `curInstance.onClose ===` `'function'` `&& curInstance.onClose()`
`})`
`return` `instance;`
`}`
generateInstance函數中,首先利用ToastConstructor構造函數建立一個Toast組件的實例,並經過propsData傳入屬性值,同時經過 $mount(document.createElement('div'))渲染該組件。

ToastConstructor是經過Vue.extend創造Toast組件的構造函數,關於這部分的具體原理,能夠參考
基於Vue構造器建立Form組件的通用解決方案dom

`/* 初始化每一個toast對象在頁面中的垂直屬性 */`
`function` `initVerticalOffset(position) {`
`// 篩選同一方向的Toast組件`
`let typeInstances = instances.filter(item => item.position === position)`
`// 計算偏移量`
`return` `typeInstances.reduce((sum, elem) =>`
`(elem.$el.offsetHeight + sum + verticalOffset),`
`verticalOffset)`
`}`
以後當某個Toast關閉時,須要更新全部Toast實例在頁面中偏移量
`/* 更新每一個toast對象在頁面中的垂直屬性 */`
`function` `updateVerticalOffset(removeInstance) {`
`let index = 0`
`let removeHeight = removeInstance.verticalOffset`
`instances.find((elem, i) => {`
`if` `(elem.id === removeInstance.id) index = i`
`})`
`// 刪除關閉的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組件的建立、如何在頁面中初始化、更新的位置。

Toast組件

組件的功能比較簡單,只須要展現信息,以及具有自動關閉、手動關閉兩個功能,屬性也要包括Toast的類型、位置、內容等。

組件的生命週期函數

`let instance =` `new` `ToastConstructor({`
`propsData: options`
`}).$mount(document.createElement(``'div'``))`
當Toast組件$mount調用時,會觸發mounted的生命週期
`mounted() {`
`// 掛載Toast在頁面中`
`document.body.appendChild(``this``.$el);`
`// 須要自動關閉時,調用startTimer`
`if` `(``this``.autoClose)` `this``.startTimer();`
`},`
`beforeDestroy() {`
`this``.stopTimer();`
`this``.$el.removeEventListener(``"transitionend"``,` `this``.destroyElement);`
`},`
`destroyed() {`
`// 註銷`
`this``.$el.parentNode.removeChild(``this``.$el);`
`}`

自動關閉

須要自動時,就要在利用setTimeout完成該功能,並在註銷時clearTimeout掉,防止泄露。
`startTimer() {`
`if` `(``this``.duration > 0) {`
`this``.timer = setTimeout(() => {`
`if` `(!``this``.closed) {`
`this``.close();`
`}`
`},` `this``.duration);`
`}`
`},`
`stopTimer() {`
`if` `(``this``.timer) clearTimeout(``this``.timer);`
`}`

3. 使用

進一步將其封裝成Vue的插件
`export` `default` `{`
`install (Vue) {`
`Vue.prototype.$toast = (options = {}) => {...}`
`}`
`}`
而且對所須要傳入的必需屬性,作處理異常處理
`export` `default` `{`
`install (Vue) {`
`Vue.prototype.$toast = (options = {}) => {...}`
`}`
`}`

總結
經過封裝一個Toast插件,提取不一樣業務之間公共的部分,減小業務的工做量。
好了,以上就是這篇文章的所有內容了,但願本文的內容對你們的學習或者工做具備必定的參考學習價值學習

相關文章
相關標籤/搜索