我使用了
Proxy
来解决这个问题,结合一个包装器。
首先,设置一个函数,作为代理的包装器。包装器接收事件对象并设置其值以供后续使用。下面会进一步解释原因。
function AdaptedEvent(ev) {
const initialEvent = ev;
let newTarget = 'your new target';
return {
get: (target, prop) => {
}
};
}
然后在代理服务器内,我有以下设置
get: (target, prop) => {
if (prop === 'target') {
return newTarget ? newTarget : initialEvent.target;
}
return target[prop];
}
当在您的代理对象上调用
.target
时,它将执行上述if体中描述的语句。它将返回一个新的目标,而不是事件的初始目标。
一旦您设置了代理,处理单击事件时,您必须构造一个代理对象。例如:
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);
}
document.querySelector('#foo').addEventListener('click', e => handleClick(new Proxy(e, new AdaptedEvent(e))));
<button id="foo">click me!</button>
但是,正如您提到的问题,在我尝试时也遇到了这个问题:
引用:
使用代理处理程序似乎可以解决这个问题,代理处理程序还可以用于隐藏某些属性。但我在这里遇到的唯一问题是,仍然无法在代理上执行像stopPropagation这样的函数(再次出现“非法调用”的错误)。
在下面的示例中,我将按钮替换为链接。假设我想使用.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);
}
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
函数的原因,它接收一个事件对象作为参数。 现在,当调用属性时是一个函数(可以轻松检查时),您可以传递该对象。
当您单击链接时,阻止事件冒泡。
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);
}
document.querySelector('#foo').addEventListener('click', e => handleClick(new Proxy(e, new AdaptedEvent(e))));
<a id="foo" href="www.google.com">click me!</a>