我創建了一個類來跟蹤不同的事件偵聽器,以便更輕松、更簡化地從元素中動態添加和洗掉事件偵聽器。類的精簡版:
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);
}
}
我還有一個較小的類,用于以正確的格式生成偵聽器以使用 ElementListenerState 類:
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 物件中洗掉其他事件偵聽器,因此控制臺不會列印任何錯誤,但 chrome 開發工具顯示這些事件仍然附加。
在這兩種方法中,函式都來自 ListenerObject 的回呼屬性,因此該函式應該是在 addListener 中應用的確切函式,而不是副本。
我不確定問題出在哪里,或者為什么它只發生在 mouseup 和 touchend 事件中。有人有一些見識嗎?
為清楚起見,在我的代碼中應用 mouseup 和 touchend 事件時,我沒有指定任何引數,但這應該不是問題,因為我已經對一些 mousemove 和 touchmove 事件做了同樣的事情,這些事件確實被 removeListenerType 方法正確洗掉.
uj5u.com熱心網友回復:
在結束之前回答我自己的問題:事實證明,這個問題與事件型別無關,而是一種糟糕的拼接方法。在我的 removeListenerType 方法中,在將串列設定為更新的注冊監聽器之前,我有邏輯從注冊串列的副本中洗掉找到的監聽器。我不知何故忘記將第二個引數添加到 splice 方法中,無意中洗掉了在找到的偵聽器之后出現的陣列中的任何內容,從而阻止了 removePrevListeners 或 removeListenerType 在下一次呼叫時正常作業。令人尷尬的錯誤,但我想它會發生。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/459030.html
標籤:javascript 班级 dom dom 事件
