正如JLRishe在他的回答中所正确说的,Event对象的目标字段不一定是一个Element。然而,我们可以确定,任何继承自UIEvent的事件在监听器中始终会有一个target字段,该字段的类型实现了Node接口,只有Windows这种情况除外。我将以这种方式介绍这个异常(使用点击事件的示例):
window.addEventListener('click', e => {
console.log(e.target)
console.log(e.target instanceof Node)
}
window.dispatchEvent(new MouseEvent('click'))
在所有其他情况下,它将是从
Node
继承的任何类型。
为什么是Node而不是Element?
那是个很好的问题。可以公正地说,如果事件是由用户与GUI的交互本地触发的,那么它将始终是实现Element的一种类型。但仍然有可能人为地调用任何UIEvent:
const node = document.createTextNode('')
document.body.appendChild(node)
window.addEventListener('click', e => {
console.log(e.target instanceof Element))
}
node.dispatchEvent(new MouseEvent('click', {bubbles: true}))
虽然这个例子是关于球形真空的,但它是可能的。
所有这些都非常有趣,但也很困难。这就是为什么我建议使用一个包,它可以处理所有可能的情况并自动输出安全类型。这个包就是types-spring。为了清晰起见:
listener 是 HTMLElement
原始类型:
const elem = document.querySelector('div')
if (elem) elem.addEventListener('click', e => {
e.target
if (e.currentTarget)
{
e.currentTarget
}
})
有类型-春天:
const elem = document.querySelector('div')
if (elem) elem.addEventListener('click', e => {
e.target
if (e.currentTarget)
{
e.currentTarget
}
})
监听器是窗口
原始类型:
window.addEventListener('click', e => {
if (e.target) {
if (e.isTrusted === true) {
e.target
}
if (e.target instanceof Window) {
e.target
}
else {
e.target
}
}
})
使用spring类型:
window.addEventListener('click', e => {
if (e.target) {
if (e.isTrusted === true) {
e.target
}
if ('atob' in e.target) {
e.target
}
else {
e.target
}
}
})
希望这个包能够帮助日常开发。
附言:对于这个有什么想法吗?
var element = ev.target as HTMLElement
的意思是将ev.target
转换成HTMLElement
类型并赋值给变量element
。 - Adrian Moisa