[英]Javascript/DOM: How to remove all event listeners of a DOM object?
[英]How to mutate a DOM event object
我處在一種情況,我必須寫自己的事件冒泡。 因此,我需要將給定的Event-Object (最初從Browser / DOM創建)傳遞給多個函數/實例,但我需要更改.target
屬性。
問題 :幾乎所有屬性的屬性描述符都否定任何突變,刪除或更改。 此外,似乎無法使用Object.assign
克隆或復制整個Event-Object,或使用Object.getOwnPropertyNames
或Object.keys
讀取屬性。
當然可以通過分配它們來手動將所有屬性復制到新對象中,但這看起來非常愚蠢。
我試圖變得非常聰明,只使用原始事件對象作為新對象的原型,只是遮蔽我想要變異的屬性。 喜歡
Object.setPrototypeOf( customEvent, event );
但是,如果我這樣做,任何對customEvent
屬性的訪問都會拋出:
Uncaught TypeError: Illegal invocation
如果我們使用也可用於遮蔽某些屬性的代理處理程序 ,它似乎確實有效。 我在這里stopPropagation
的唯一問題是,仍然無法通過代理執行stopPropagation
函數( Uncaught TypeError:非法再次調用 )。
問題 :操作/擴展DOM事件對象的最佳實踐是什么?
如果你提到任何形式或形狀的jQuery,你將遭受7年的不幸。
我已經使用Proxy
來解決這個問題,並結合了包裝器。
首先,設置一個充當代理的包裝器的函數。 包裝器接收一個Event對象並設置其值以供以后使用。 其原因將進一步解釋。
function AdaptedEvent(ev) {
const initialEvent = ev;
let newTarget = 'your new target'; // can be dynamic if you wish.
// returning with a handler for proxy
return {
get: (target, prop) => {
// proxy'ing stuff
}
};
}
然后在代理內部,我有
get: (target, prop) => {
if (prop === 'target') {
return newTarget ? newTarget : initialEvent.target;
}
return target[prop];
}
當你的代理對象調用.target
時,它將執行上面if-body中描述的語句。 它將返回一個新目標而不是事件的初始目標。
設置代理后,必須在處理單擊事件時構造代理對象。 喜歡
document.querySelector('#foo').addEventListener(
'click',
e => handleClick(new Proxy(e, new AdaptedEvent(e)))
);
例:
function AdaptedEvent(ev) { const initialEvent = ev; let newTarget = 'your new target'; return { get: (target, prop) => { if (prop === 'target') { return newTarget ? newTarget : initialEvent.target; } return target[prop]; } }; } function handleClick(event) { console.log(event.target); console.log(event.which); } // binding click event. document.querySelector('#foo').addEventListener('click', e => handleClick(new Proxy(e, new AdaptedEvent(e))));
<button id="foo">click me!</button>
但正如你提到的那樣,我在嘗試時也看到了一個問題:
如果我們使用也可用於遮蔽某些屬性的代理處理程序,它似乎確實有效。 我在這里
stopPropagation
的唯一問題是,仍然無法通過代理執行stopPropagation
函數( Uncaught TypeError:非法再次調用 )。
在下面的例子中; 我已將按鈕替換為鏈接。 假設我想通過使用.preventDefault()
來阻止它冒泡。 你可以看到它會引發上面提到的錯誤。
function AptEvent(ev) { const initialEvent = ev; let newTarget = 'your new target'; return { get: (target, prop) => { if (prop === 'target') { return newTarget ? newTarget : initialEvent.target; } return target[prop]; } }; } function handleClick(event) { event.preventDefault(); console.log(event.target); console.log(event.which); } // binding click event. document.querySelector('#foo').addEventListener('click', e => handleClick(new Proxy(e, new AptEvent(e))));
<a id="foo" href="www.google.com">click me!</a>
這樣做的原因是,在調用所述函數時,您已經失去了調用preventDefault
的正確上下文。 對此的解決方案是使用.bind
。 但是你應該把什么傳遞給.bind
? 是的,本機Event
對象。 這就是為什么我設置了上面的AdaptedEvent
函數,它接收一個Event對象作為參數。 現在,您可以在對屬性的調用是函數時輕松傳遞該對象(輕松檢查)。
單擊鏈接時,事件冒泡停止。
function AdaptedEvent(ev) { const initialEvent = ev; let newTarget = 'your new target'; return { get: (target, prop) => { if (Object.prototype.toString.call(target[prop]) === '[object Function]') { return target[prop].bind(initialEvent); } else if (prop === 'target') { return newTarget ? newTarget : initialEvent.target; } return target[prop]; } }; } function handleClick(event) { event.preventDefault(); console.log(event.target); console.log(event.which); } // binding click event. document.querySelector('#foo').addEventListener('click', e => handleClick(new Proxy(e, new AdaptedEvent(e))));
<a id="foo" href="www.google.com">click me!</a>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.