Let*_*ion 7 javascript typescript
我大致有以下几点:
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; }}                                                                                                                                                                   
  />)
}
Run Code Online (Sandbox Code Playgroud)
此代码正确检测用户是否在CustomElement内部或外部单击,到目前为止一切顺利.
但是,tsc对此并不满意:
error TS2345: Argument of type 'EventTarget' is not assignable to parameter of type 'Node'.
  Property 'attributes' is missing in type 'EventTarget'.
Run Code Online (Sandbox Code Playgroud)
综观node_modules/typescript/lib/lib.d.ts这是有意义的,因为e.target是EventTarget它似乎仅限定用于添加和移除事件处理程序的功能.但是,MDN表示e.target是"对调度事件的对象的引用".这听起来更接近我想要的.
那么如何保持当前正在运行的功能,同时使tsc满意(而不是仅仅消除错误)?
Let*_*ion 14
我在typescript问题队列中发现了类似的讨论,在这种情况下说类型断言可能是不可避免的:
基本上,EventTarget是最常用的类型,其中Element是子类型,而HTMLElement是其子类型.如果从DOM中取回一个东西,我们通常不知道它是什么,你应该添加一个类型断言来"添加"你对特定DOM布局结构的具体外部知识.
例如,事件的.target可能不是元素(例如,您可以向XMLHttpRequest添加事件侦听器,而XMLHttpRequest没有getBoundingClientRect方法).
所以因为目标可能或者可能不是Node我想要的,TS无法推断真相,我需要断言.
contains(e.target as Node) 似乎是正确的解决方案.
Ami*_*mid 12
如何像这样定义你的点击处理程序:
private click = (e: Event) =>
{
    if (e.target instanceof HTMLElement && !ReactDOM.findDOMNode(this.someRef).contains(e.target))
    {
        if (this.state.toggled)
        {
            this.setState({ toggled: false });
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
样品笔。
这对我有用,重点是你还应该为你的 ref 提供一个类型:
 const wrapperRef = useRef<HTMLDivElement>(null);
  const handleClickOutside = (event: React.MouseEvent) => {
    if (
      wrapperRef?.current?.contains(event.target as Node) &&
      isFocusLockDisabled
    ) {
      return foo(false);
    }
  };
Run Code Online (Sandbox Code Playgroud)