jAn*_*ndy 5 javascript dom dom-events
我处在一种情况下,我不得不编写自己的事件冒泡。因此,我需要将给定的事件对象(最初是从浏览器/ DOM创建的)传递给多个函数/实例,但是例如,我需要更改.target属性。
问题:几乎所有属性的属性描述符都拒绝任何突变,删除或更改。此外,它似乎不是可以克隆或复制整个事件对象使用Object.assign或使用属性读取Object.getOwnPropertyNames或Object.keys。
当然可以通过分配属性将所有属性手动复制到新对象中,但这似乎很愚蠢。
我试图变得非常聪明,只是将原始的事件对象用作新对象的原型,以仅遮盖我要更改的属性。喜欢
Object.setPrototypeOf( customEvent, event );
Run Code Online (Sandbox Code Playgroud)
但是,如果我这样做,则可以使用以下方式访问customEventthrow 属性:
未捕获的TypeError:非法调用
如果我们使用代理处理程序(也可以用于遮盖某些属性),它似乎确实起作用。我这里唯一的问题是,仍然无法像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
}
};
}
Run Code Online (Sandbox Code Playgroud)
然后在代理内部,我有
get: (target, prop) => {
if (prop === 'target') {
return newTarget ? newTarget : initialEvent.target;
}
return target[prop];
}
Run Code Online (Sandbox Code Playgroud)
当.target在代理对象上调用时,它将执行上面 if-body 中描述的语句。它将返回一个新目标,而不是事件的初始目标。
设置代理后,您必须在处理单击事件时构造代理对象。喜欢
document.querySelector('#foo').addEventListener(
'click',
e => handleClick(new Proxy(e, new AdaptedEvent(e)))
);
Run Code Online (Sandbox Code Playgroud)
例子:
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
}
};
}
Run Code Online (Sandbox Code Playgroud)
get: (target, prop) => {
if (prop === 'target') {
return newTarget ? newTarget : initialEvent.target;
}
return target[prop];
}
Run Code Online (Sandbox Code Playgroud)
但正如你提到的一个我在尝试时也看到的问题:
如果我们使用代理处理程序,它似乎确实有效,该代理处理程序也可用于隐藏某些属性。我在这里遇到的唯一问题是,仍然无法
stopPropagation通过代理执行类似的函数(未捕获的类型错误:再次非法调用)。
在下面的例子中;我已将按钮替换为链接。假设我想通过使用来停止它的冒泡.preventDefault()。您可以看到它会抛出上述错误。
document.querySelector('#foo').addEventListener(
'click',
e => handleClick(new Proxy(e, new AdaptedEvent(e)))
);
Run Code Online (Sandbox Code Playgroud)
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))));Run Code Online (Sandbox Code Playgroud)
这样做的原因是,当调用该函数时,您已经丢失了调用的正确上下文preventDefault。一个解决方案是使用.bind. 但是你应该传递什么给 呢.bind?是的,原生Event对象。这就是为什么我设置了上面的内容AdaptedEvent函数来接收 Event 对象作为参数。现在,当对属性的调用是函数时(很容易被检查),您可以传递对象。
当您单击链接时,事件冒泡停止。
<button id="foo">click me!</button>Run Code Online (Sandbox Code Playgroud)
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))));Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
526 次 |
| 最近记录: |