實現一個簡單的Toast插件,方便遷移到不一樣的項目中,用來全局提示、警告一些信息。前端
概述: 在前端項目中,有時會須要通知、提示一些信息給用戶,尤爲是在後臺系統中,操做的正確與否,都須要給與用戶一些信息。git
在Vue組件的methods
內,調用以下代碼github
this.$toast({
content: "可自動關閉",
autoClose: true
})
複製代碼
在頁面的右側會出現一個Toast彈框,屢次點擊時,會依照順序進行顯示,而且Toast可自動關閉,具體效果如圖。 app
代碼地址:Github UI-Librarydom
代碼結構ide
將Toast插件分爲兩個部分:函數
data
,並在其生命週期完成在頁面中的掛載與銷燬;Toast方法工具
爲了可以經過this.$toast({...})
調用Toast組件,須在Vue的prototype
上添加一個方法,以下post
let instances = []
let initIndex = 0
Vue.prototype.$toast = (options = {}) => {
/* 建立一個Toast組件的實例 */
let instance = generateInstance(options)
/* 將單個toast存入隊列中 */
instances.push(instance)
}
複製代碼
當調用該方法時,經過generateInstance
建立一個Toast組件的實例,並將其放入instances
,統一管理。ui
/* 構造單個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組件的通用解決方案。
initVerticalOffset
函數計算Toast組件的初始偏移量
/* 初始化每一個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
// 兼容ie 去掉find method
for (; index < instances.length; index++) {
if (instances[index].id === removeInstance.id) break;
}
instances.splice(index, 1);
// 刪除關閉的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);
}
複製代碼
進一步將其封裝成Vue的插件
export default {
install (Vue) {
Vue.prototype.$toast = (options = {}) => {...}
}
}
複製代碼
而且對所須要傳入的必需屬性,作處理異常處理
let requireProps = Object.keys(Toast.props)
.filter((elem) => (Toast.props[elem].required))
requireProps.forEach((elem) => {
if (!options[elem]) throw `err: options lack ${elem} prop`
})
if ( options.type && !types.some(elem => elem === options.type) )
throw `err: toast not exist ${options.type} type`
複製代碼
經過封裝一個Toast插件,提取不一樣業務之間公共的部分,減小業務的工做量。
往期文章:
原創聲明: 該文章爲原創文章,轉載請註明出處。