簡體   English   中英

removeEventListener 不適用於 touchend 和 mouseup 偵聽器

[英]removeEventListener does not work for touchend and mouseup listeners

我制作了一個 class 來跟蹤不同的事件偵聽器,以便更輕松、更簡化地動態添加和刪除元素中的事件偵聽器。 class 的精簡版:

class ElementListenerState {
    /**
     * @param {object} element - pass DOM element to track listeners for (required)
     * @param {[object]} initialListeners - Initial list of Listeners to register (optional)
     * @returns
     */
    constructor(element, initialListeners = []) {
        this.element = element;
        this.currentListeners = initialListeners || [];
    }
    /**
     *
     * @returns {[]} a copy array of currentListeners
     */
    getCurrentListeners() {
        return [...this.currentListeners];
    }

    setCurrentListeners(arr) {
        this.currentListeners = arr;
    }

    removePrevListeners() {
        const prevListeners = this.getCurrentListeners();
        prevListeners.forEach((listener) => {
            this.element.removeEventListener(
                listener.eventType,
                listener.callback
            );
        });
        this.setCurrentListeners([]);
    }

    removeListenerType(type) {
        const currentListeners = this.getCurrentListeners();
        const listenersToRemove = currentListeners.filter(
            (listener) => listener.eventType === type
        );
        // if(!listenersToRemove.length) console.warn(`No listeners with type ${type} found.`)
        listenersToRemove.forEach((listener) => {
            this.element.removeEventListener(
                listener.eventType,
                listener.callback
            );
            currentListeners.splice(
                currentListeners.findIndex((listenerInArr) =>
                    listenerInArr === listener
                )
            );
        });
        this.setCurrentListeners(currentListeners);
    }

    /**
     *
     * @param {object} listener
     * @returns Error code -1 will be returned if listener is already registered, nothing will be returned if method was successful.
     */
    addListener(listener) {
        // Return error code if listener already registered in list
        if (this.getCurrentListeners().includes(listener)) {
            console.warn("Provided listener is already registered in list!");
            return -1;
        }
        this.element.addEventListener(listener.eventType, listener.callback);
        const newListeners = this.getCurrentListeners();
        newListeners.push(listener);
        this.setCurrentListeners(newListeners);
    }
}

我還有一個較小的 class,用於以正確的格式生成偵聽器以與 ElementListenerState class 一起使用:

class ListenerObject {
    /**
     *
     * @param {string} eventType represents the type of event listener
     * @param {function} handler callback function for event listener
     * @param {[]} args Array of arguments (in proper order) for callback function, defaults to empty array
     */
    constructor(eventType, handler, args = []) {
        this.eventType = eventType;
        this.callback = (e) => handler(e, ...args);
    }
}

在添加和刪除 MOST 事件偵聽器時,這兩個類的功能完全符合預期,但如果事件偵聽器類型為“mouseup”或“touchend”,則 ListenerObject 會從 currentListeners 數組中刪除,但實際上不會從 DOM 元素中刪除. 使用 removePrevListeners 方法和 removeListenerType 事件時會發生此問題。

沒有錯誤打印到控制台,因為我代碼中的所有 touchend 和 mouseup 事件正在做的是從 ElementListenerState object 中刪除其他事件偵聽器,但 chrome 開發工具顯示這些事件仍然附加。

在這兩種方法中,function 來自 ListenerObject 的回調屬性,因此 function 應該是在 addListener 中應用的確切 function 而不是副本。

我不確定問題出在哪里,或者為什么它只發生在 mouseup 和 touchend 事件中。 任何人都有一些見識?

為清楚起見,在我的代碼中應用 mouseup 和 touchend 事件時,我沒有指定任何參數,但這應該不是問題,因為我對一些 mousemove 和 touchmove 事件做了同樣的事情,這些事件確實被 removeListenerType 方法正確刪除了.

關閉前回答我自己的問題:事實證明這個問題與事件類型無關,而是一個糟糕的拼接方法。 在我的 removeListenerType 方法中,我有邏輯在將列表設置為更新的注冊偵聽器之前從已注冊列表的副本中刪除找到的偵聽器。 我不知何故忘記將第二個參數添加到 splice 方法,無意中刪除了數組中出現在找到的偵聽器之后的任何內容,從而阻止 removePrevListeners 或 removeListenerType 在下一次調用時正常工作。 令人尷尬的錯誤,但我想它會發生。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM