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 & 总结
相关文章
相关标签/搜索