VUE - MVVM - part7 - Event

看這篇以前,若是沒有看過以前的文章,可拉到文章末尾查看以前的文章。vue

事件是什麼?

在標準瀏覽器中,咱們常用:addEventListener 來爲一個 DOM 添加一個事件(clickmousemovetap等)。node

在我看來,一個事件是一種行爲(或狀況),當發生這種行爲(或狀況)時,咱們要去作的事,好比今天下雨了,那我就得去找傘;鬧鐘響了,那我就得起牀等等。git

仔細看這些狀況,歸結到代碼中,無非就是一個行爲(或狀況)的名稱,和一些列的動做,而在 js 中動做就是 function,一系列的動做就是一個函數的集合。github

實現

如上所說,咱們把事件抽象成一個類數組

類下屬性 & 方法瀏覽器

  • _events 一個對象 {key: eventName, value: Array<Function,Function...>}
  • $on(eventName, func) 添加具體事件的處理函數
  • $off(eventName) 取消事件處理函數
  • $emit(eventName, data1, data2, ...) 用於觸發事件
  • $once(eventName, func) 設置僅觸發一次的事件

ok 根據咱們的構想,在來看這個實現好的 Eventapp

let uid = 0

export class Event {
    constructor() {
        this.id = ++uid
        this._events = {}
    }

    $on(eventName, fn) {
        let ctx = this;
        // 若 _events 對象下無對應事件名,則新建一個數組,而後將處理函數推入數組
        if(!ctx._events[eventName]){
            ctx._events[eventName] = []
        }
        ctx._events[eventName].push(fn)
        return ctx
    }

    $once(eventName, fn) {
        let ctx = this

        function on() {
            // 先取消,而後觸發,確保僅觸發一次
            ctx.$off(eventName, on)
            fn.apply(ctx, arguments)
        }

        on.fn = fn
        ctx.$on(eventName, on)
        return object
    }

    $off(eventName) {
        let ctx = this
        const cbs = ctx._events[eventName]
        if (cbs) {
            // 取消置空便可
            ctx._events[eventName] = null
        }
        return ctx
    }

    $emit(eventName, ...args) {
        let ctx = this
        let cbs = ctx._events[eventName]
        if (cbs) {
            cbs.forEach(func => func.apply(ctx, args))
        }
        return ctx
    }

}

一個簡單的事件管理的類便實現好了,讓咱們來測試一下:函數

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 一個簡易的事件管理實現了,因爲這節內容與上幾節關係不大,因此這裏再次說下測試代碼的運行方式:測試

  1. node 環境 8.11.1 往上,否則不可以支持 import 語法
  2. 爲了避免轉碼支持 import 語法,文件後綴爲 .mjs
  3. 進入到 test.mjs 所在目錄命令行運行:node --experimental-modules test.mjs 便可

點擊查看相關代碼優化

系列文章地址

  1. VUE - MVVM - part1 - defineProperty
  2. VUE - MVVM - part2 - Dep
  3. VUE - MVVM - part3 - Watcher
  4. VUE - MVVM - part4 - 優化Watcher
  5. VUE - MVVM - part5 - Observe
  6. VUE - MVVM - part6 - Array
  7. VUE - MVVM - part7 - Event
  8. VUE - MVVM - part8 - 優化Event
  9. VUE - MVVM - part9 - Vue
  10. VUE - MVVM - part10 - Computed
  11. VUE - MVVM - part11 - Extend
  12. VUE - MVVM - part12 - props
  13. VUE - MVVM - part13 - inject & 總結
相關文章
相關標籤/搜索