实现一个自定义event事件,包括on ,off,trigger,once

on监听事件,off取消事件 ,trigger触发事件,once只执行一次

class Event {
    constructor() {
        this.handlers = {};//记录所有的事件以及处理函数
        /*
            {
                click:[fn1,fn2],
                mouseover: [fn3,fn4]
            }
        */
    }
    /**
     * on 添加事件监听
     * @param {事件类型} type 
     * @param {事件处理函数} handler 
     */
    on(type, handler, once = false) {
        if (!this.handlers[type]) {
            this.handlers[type] = [];
        }
        if (!this.handlers[type].includes(handler)) {
            this.handlers[type].push(handler);
            handler.once = once;
        }
    }

    /**
     * off  取消事件监听
     * @param {要取消的事件类型} type 
     * @param {要取消的事件函数,如果不传则清除所有} handler 
     */
    off(type, handler) {
        if (this.handlers[type]) {
            if (handler === undefined) {
                this.handlers[type] = [];
            } else {
                this.handlers[type] = this.handlers[type].filter(f => f != handler);
            }
        }
    }

    /**
     * trigger 执行函数
     * @param {要执行哪个类型的函数} type 
     * @param {事件对象} eventData 
     * @param {this执行} point 
     */
    trigger(type, eventData = {}, point = this) {
        if (this.handlers[type]) {
            this.handlers[type].forEach(f => {
                f.call(point, eventData);
                if (f.once) {
                    this.off(type, f);
                }
            });
        }
    }

    /**
     * once 只执行一次
     * @param {事件类型} type 
     * @param {要执行的函数} handler 
     */
    once(type, handler) {
        this.on(type, handler, true);
    }
}

测试脚本

let e = new Event;
        e.on("click", () => {
            console.log(1);

        })
        e.on("click", () => {
            console.log(2);

        })
        function fn3() {
            console.log(3);

        }
        e.on("click", fn3);
        console.log(e);

或者可以使用上一章节的内容进行测试https://www.cnblogs.com/yinping/p/10697083.html

在function函数添加监听函数

(function () {
            let box = document.querySelector("#box");
            let dragbox = new Drag(box);
            dragbox.on("dragstart", function (e) { //这里不可以使用箭头函数,否则trigger的call方法无效
                console.log(e, this);

                console.log("开始拖拽");

                this.style.background = "yellow";
            })
            dragbox.on("dragend", function (e) {
                console.log(e, this);

                this.style.background = "red";
            })
            dragbox.once("drag", function () {
                console.log("drag");
            })
        })()

同时在move,start中添加触发函数

class Drag extends Event {
            //构造函数
            constructor(el) {
                super();
                this.el = el;
                //鼠标摁下时的元素位置
                this.startOffset = {};
                //鼠标摁下时的鼠标位置
                this.startPoint = {};
                let move = (e) => {
                    this.move(e);
                };
                let end = (e) => {
                    document.removeEventListener("mousemove", move);
                    document.removeEventListener("mouseup", end);
                    this.trigger("dragend", e, this.el);
                };
                el.addEventListener("mousedown", (e) => {
                    this.start(e);
                    document.addEventListener("mousemove", move);
                    document.addEventListener("mouseup", end);
                })
            }
            //摁下时的处理函数
            start(e) {
                let { el } = this;
                this.startOffset = {
                    x: el.offsetLeft,
                    y: el.offsetTop
                }
                this.startPoint = {
                    x: e.clientX,
                    y: e.clientY
                }
                this.trigger("dragstart", e, el);

            }
            //鼠标移动时的处理函数
            move(e) {
                let { el, startOffset, startPoint } = this;
                let newPoint = {
                    x: e.clientX,
                    y: e.clientY
                }
                let dis = {
                    x: newPoint.x - startPoint.x,
                    y: newPoint.y - startPoint.y,
                }
                el.style.left = dis.x + startOffset.x + "px";
                el.style.top = dis.y + startOffset.y + "px";
                this.trigger('drag', e, el);
            }
        }
原文地址:https://www.cnblogs.com/yinping/p/10697152.html