實現一個簡單的Toast外掛,方便遷移到不同的專案中,用來全域性提示、警告一些資訊。
概述: 在前端專案中,有時會需要通知、提示一些資訊給使用者,尤其是在後臺系統中,操作的正確與否,都需要給與使用者一些資訊。
1. 例項
在Vue元件的methods
內,呼叫如下程式碼
this.$toast({
content: "可自動關閉",
autoClose: true
})
複製程式碼
在頁面的右側會出現一個Toast彈框,多次點選時,會依照順序進行顯示,並且Toast可自動關閉,具體效果如圖。
程式碼地址:Github UI-Library
2. 原理
-
程式碼結構
將Toast外掛分為兩個部分:
- Toast元件本身,包含本身的dom結構以及
data
,並在其生命週期完成在頁面中的掛載與銷燬; - 在元件外構建一層代理並提供相關方法用於呼叫、並控制多個Toast在頁面中顯示的順序。
- Toast元件本身,包含本身的dom結構以及
-
Toast方法
為了能夠通過
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元件的通用解決方案。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); } 複製程式碼
3. 使用
進一步將其封裝成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`
複製程式碼
4. 總結
通過封裝一個Toast外掛,提取不同業務之間公共的部分,減少業務的工作量。
往期文章:
- 從零實現Vue的元件庫(零)- 基本結構以及構建工具
- 從零實現Vue的元件庫(一)- Toast 實現
- 從零實現Vue的元件庫(二)- Slider 實現
- 從零實現Vue的元件庫(三)- Tabs 實現
- 從零實現Vue的元件庫(四)- File-Reader 實現
- 從零實現Vue的元件庫(五)- Breadcrumb 實現
- 從零實現Vue的元件庫(六)- Hover-Tip 實現
- 從零實現Vue的元件庫(七)- Message-Box 實現
- 從零實現Vue的元件庫(八)- Input 實現
- 從零實現Vue的元件庫(九)- InputNumber 實現
- 從零實現Vue的元件庫(十)- Select 實現
- 從零實現Vue的元件庫(十一)- Date-picker 實現
- 從零實現Vue的元件庫(十二)- Table 實現
- 從零實現Vue的元件庫(十三)- Pagination 實現
- 從零實現Vue的元件庫(十四)- RadioGroup 實現
- 從零實現Vue的元件庫(十五)- CheckboxGroup 實現
原創宣告: 該文章為原創文章,轉載請註明出處。