雖然實現 Vue
的 MVVM
已經走到第 7
步,但這節內容與之前的內容相關性不大,但若想要了解整個 MVVM
的實現,還是先移步看之前已經實現的 6
步
- 簡單實現 VUE 中 MVVM – step1 – defineProperty
- 簡單實現 VUE 中 MVVM – step2 – Dep
- 簡單實現 VUE 中 MVVM – step3 – Watcher
- 簡單實現 VUE 中 MVVM – step4 – 優化Watcher
- 簡單實現 VUE 中 MVVM – step5 – Observe
- 簡單實現 VUE 中 MVVM – step6 – Array
事件是什麼?
在標準瀏覽器中,我們經常使用:addEventListener
來為一個 DOM 新增一個事件(click
、mousemove
、tap
等)。
在我看來,一個事件是一種行為(或情況),當發生這種行為(或情況)時,我們要去做的事,比如今天下雨了,那我就得去找傘;鬧鐘響了,那我就得起床等等。
仔細看這些情況,歸結到程式碼中,無非就是一個行為(或情況)的名稱,和一些列的動作,而在 js
中動作就是 function
,一系列的動作就是一個函式的集合。
實現
如上所說,我們把事件抽象成一個類
類下屬性 & 方法
- _events/Object: 用於存放事件名稱(key/String)和一些列的動作(value/Array<Function,Function…>)
- $on(eventName, func)/Function: 用於新增具體事件的處理函式
- $off(eventName)/Function: 既然有新增肯定是有取消
- $emit(eventName, data1, data2, …)/Function: 用於觸發事件
- $once(eventName, func)/Function: 用於新增僅僅觸發一次的事件,作為一個語法糖的存在,比如你想在特定時間設定一個鬧鐘,顯然這個鬧鐘並不是你的起床鬧鐘,僅僅需要觸發一次就夠了
ok 根據我們的構想,在來看這個實現好的 Event
類
let uid = 0
export class Event {
constructor() {
this.id = ++uid
this._events = {}
}
$on(eventName, fn) {
let object = this;
// 若 _events 物件下無對應事件名,則新建一個陣列,然後將處理函式推入陣列
(object._events[eventName] || (object._events[eventName] = [])).push(fn)
return object
}
$once(eventName, fn) {
let object = this
function on() {
// 先取消,然後觸發,確保僅觸發一次
object.$off(eventName, on)
fn.apply(object, arguments)
}
on.fn = fn
object.$on(eventName, on)
return object
}
$off(eventName) {
let object = this
const cbs = object._events[eventName]
if (cbs) {
// 取消置空即可
object._events[eventName] = null
}
return object
}
$emit(eventName, ...args) {
let object = this
let cbs = object._events[eventName]
if (cbs) {
cbs.forEach(func => func.apply(object, args))
}
return object
}
}
一個簡單的事件管理的類便實現好了,讓我們來測試一下:
import {Event} from "./Event";
let eventTest = new Event()
eventTest.$on(`testEvent`, function (event) {
console.log(`測試事件新增,傳入引數為` + event)
})
eventTest.$emit(`testEvent`, `事件觸發成功`)
// 測試事件新增,傳入引數為事件觸發成功
eventTest.$emit(`testEvent`, `事件再次觸發成功`)
// 測試事件新增,傳入引數為事件再次觸發成功
eventTest.$off(`testEvent`)
eventTest.$emit(`testEvent`, `事件取消,不會有輸出`)
// 無輸出
eventTest.$once(`testOnce`, function (event) {
console.log(`事件僅僅觸發一次,傳入引數為` + event)
})
eventTest.$emit(`testOnce`, `事件觸發成功`)
// 事件僅僅觸發一次,傳入引數為事件觸發成功
eventTest.$emit(`testOnce`, `事件取消,不會有輸出`)
// 無輸出
ok 一個簡易的事件管理實現了,由於這節內容與上幾節關係不大,所以這裡再次說下測試程式碼的執行方式:
-
node
環境8.11.1
往上,不然不能夠支援import
語法 - 為了不轉碼支援
import
語法,檔案字尾為.mjs
- 進入到
test.mjs
所在目錄命令列執行:node --experimental-modules test.mjs
即可
更多內容,可以訪問http://blog.acohome.cn