看這篇前如果沒看過 step7
移步檢視,事件和前 6
步關係不大,主要看下 step7
:
- 實現 VUE 中 MVVM – step1 – defineProperty
- 實現 VUE 中 MVVM – step2 – Dep
- 實現 VUE 中 MVVM – step3 – Watcher
- 實現 VUE 中 MVVM – step4 – 優化Watcher
- 實現 VUE 中 MVVM – step5 – Observe
- 實現 VUE 中 MVVM – step6 – Array
- 實現 VUE 中 MVVM – step7 – Event
回顧
在上一步我們實現了一個簡易的事件管理的類,接下來我們把它給優化下,方便我們的使用。主要優化內容:
- 方便為多個事件新增同一個函式
- 方便為一個事件新增多個函式
- 有針對性的取消事件的函式
第一點和第二點都要修改 $on
函式,所以我們一起改:
之前的程式碼
$on(eventName, fn) {
let object = this;
(object._events[eventName] || (object._events[eventName] = [])).push(fn)
return object
}
優化之後的程式碼
$on(eventName, fn) {
let object = this
if (Array.isArray(eventName)) { // 處理事件名是陣列的情況
// 遞迴呼叫 $on 函式
eventName.forEach(name => this.$on(name, fn))
} else {
// 將處理函式統一成陣列方便新增
if (!Array.isArray(fn)) { // 處理處理函式為陣列的情況
fn = [fn]
}
(object._events[eventName] || (object._events[eventName] = [])).push(...fn)
}
return object
}
很簡單的優化,但卻讓 $on
函式更加方便的使用。
接著我們來優化 $off
。我們先看看之前的程式碼:
$off(eventName) {
let object = this
const cbs = object._events[eventName]
if (cbs) {
// 取消置空即可
object._events[eventName] = null
}
return object
}
我們只做了清空特定事件,其實我們能做的還有很多,
- 清空所有事件
- 清空多個事件
- 取消特定事件的特定處理函式
優化的細節看程式碼中的註釋
$off(eventName, fn) {
let object = this
// 清空所有事件
if (!arguments.length) {
object._events = Object.create(null)
return object
}
// 清空多個事件
if (Array.isArray(eventName)) {
eventName.forEach(name => this.$off(name, fn))
return object
}
// 若沒有事件對應的函式列表則不用處理
const cbs = object._events[eventName]
if (!cbs) {
return object
}
// 清空特定事件
if (!fn) {
object._events[eventName] = null
return object
}
// 取消特定事件的特定處理函式
if (fn) {
let cb
let i = cbs.length
// 處理一次取消多個的情況
if (Array.isArray(fn)) {
fn.forEach(fnc => this.$off(eventName, fnc))
}
while (i--) {
cb = cbs[i]
if (cb === fn || cb.fn === fn) {
cbs.splice(i, 1)
break
}
}
}
return object
}
ok 優化好了,測試一下:
import {Event} from "./Event";
let eventTest = new Event()
eventTest.$on(`eventName1`, (e) => {
console.log(`一次新增一個處理函式`)
console.log(e)
})
eventTest.$on(`eventName2`, [(e) => {
console.log(`一次新增多個處理函式,第一個`)
console.log(e)
}, (e) => {
console.log(`一次新增多個處理函式,第二個`)
console.log(e)
}])
eventTest.$on([`eventName3`, `eventName4`], (e) => {
console.log(`多個事件新增同一處理函式`)
console.log(e)
})
eventTest.$on([`eventName5`, `eventName6`], [(e) => {
console.log(`多個事件新增多個處理函式,第一個`)
console.log(e)
}, (e) => {
console.log(`多個事件新增多個處理函式,第二個`)
console.log(e)
}])
eventTest.$emit(`eventName1`, `傳入引數1`)
// 一次新增一個處理函式
// 傳入引數1
eventTest.$emit(`eventName2`, `傳入引數2`)
// 一次新增多個處理函式,第一個
// 傳入引數2
// 一次新增多個處理函式,第二個
// 傳入引數2
eventTest.$emit(`eventName3`, `傳入引數3`)
// 多個事件新增同一處理函式
// 傳入引數3
eventTest.$emit(`eventName4`, `傳入引數4`)
// 多個事件新增同一處理函式
// 傳入引數4
eventTest.$emit(`eventName5`, `傳入引數5`)
// 多個事件新增多個處理函式,第一個
// 傳入引數5
// 多個事件新增多個處理函式,第二個
// 傳入引數5
eventTest.$emit(`eventName6`, `傳入引數6`)
// 多個事件新增多個處理函式,第一個
// 傳入引數6
// 多個事件新增多個處理函式,第二個
// 傳入引數6
console.log(`------------------------------`)
eventTest.$off(`eventName1`)
eventTest.$off([`eventName2`, `eventName3`])
eventTest.$emit(`eventName1`, `傳入引數1`)
// 無輸出
eventTest.$emit(`eventName2`, `傳入引數2`)
// 無輸出
eventTest.$emit(`eventName3`, `傳入引數3`)
// 無輸出
eventTest.$emit(`eventName4`, `傳入引數4`)
// 多個事件新增同一處理函式
// 傳入引數4
eventTest.$emit(`eventName5`, `傳入引數5`)
// 多個事件新增多個處理函式,第一個
// 傳入引數5
// 多個事件新增多個處理函式,第二個
// 傳入引數5
eventTest.$emit(`eventName6`, `傳入引數6`)
// 多個事件新增多個處理函式,第一個
// 傳入引數6
// 多個事件新增多個處理函式,第二個
// 傳入引數6
console.log(`------------------------------`)
eventTest.$off()
eventTest.$emit(`eventName1`, `傳入引數1`)
// 無輸出
eventTest.$emit(`eventName2`, `傳入引數2`)
// 無輸出
eventTest.$emit(`eventName3`, `傳入引數3`)
// 無輸出
eventTest.$emit(`eventName4`, `傳入引數4`)
// 無輸出
eventTest.$emit(`eventName5`, `傳入引數5`)
// 無輸出
eventTest.$emit(`eventName6`, `傳入引數6`)
// 無輸出
console.log(`------------------------------`)
這兩節吧,事件介紹了下,一個健壯的事件的類也編寫好了,接下來我們把這 8
步實現的內容集合到一個物件下,也就是 Vue
下,敬請期待。
更多內容,可以訪問http://blog.acohome.cn