Javascript 检测单击是否在react组件内部或不在typescript中

Javascript 检测单击是否在react组件内部或不在typescript中,javascript,typescript,Javascript,Typescript,我大致有以下几点: componentDidMount() { document.querySelector('body'

我大致有以下几点:

componentDidMount() {                                                                                                                                                                                           
  document.querySelector('body')!.addEventListener('click', this.click);
} 

click = (e: Event) => {                                                                                                                                                                                         
  if (this.state.toggled) {
    if (!ReactDom.findDOMNode(this.someRef).contains(e.target)) {
      this.setState({ toggled: false });
    }
  }
};

render() {
  return (<CustomElement
    ref={(e) => { this.someRef = e; }}                                                                                                                                                                   
  />)
}
查看
node\u modules/typescript/lib/lib.d.ts
这很有意义,因为
e.target
是一个
EventTarget
,它似乎只定义了添加和删除事件处理程序的函数。然而,e.target表示“对发送事件的对象的引用”,这听起来更接近我想要的


那么,我如何保留当前工作的功能,同时也使tsc满意(而不仅仅是消除错误)?

如何定义您的单击处理程序,如下所示:

private click = (e: Event) =>
{
    if (e.target instanceof HTMLElement && !ReactDOM.findDOMNode(this.someRef).contains(e.target))
    {
        if (this.state.toggled)
        {
            this.setState({ toggled: false });
        }
    }
}

示例。

我在中发现了类似的讨论,在本例中,类型断言是:

基本上EventTarget是最通用的类型,其中元素是一个子类型,HtmleElement是该类型的一个子类型。如果您从DOM中得到一个东西,我们通常不知道它是什么,您应该添加一个类型断言来“添加”关于特定DOM布局结构的特定外部知识

例如,事件的.target可能不是元素(例如,可以将事件侦听器添加到XMLHttpRequest,而XMLHttpRequest没有getBoundingClientRect方法)

因此,因为目标可能是也可能不是我想要的
节点
,TS无法推断真相,我需要断言


包含(例如,目标作为节点)
似乎是正确的解决方案。

这对我来说是可行的,重点是你还应该为你的ref提供一个类型:

const wrapperRef=useRef(null);
const handleClickOutside=(事件:React.MouseEvent)=>{
如果(
wrapperRef?current?contains(event.target作为节点)&&
isFocusLockDisabled
) {
返回foo(false);
}
};

我对这里的好处有点不清楚,在我看来,这样做可以消除错误,因此TSC现在会假设内码从不运行,因为它会认为检查的次数总是失败。试试它。我已经测试了建议的代码,它实际上总是成功的,因为HtmleElement是其他元素的基础。它不会真正消除错误(不像对任何错误进行强制转换),相反,它会进行有效的检查,如果它是真的,则会继续。我附上了一个示例供您检查。
private click = (e: Event) =>
{
    if (e.target instanceof HTMLElement && !ReactDOM.findDOMNode(this.someRef).contains(e.target))
    {
        if (this.state.toggled)
        {
            this.setState({ toggled: false });
        }
    }
}