反应流程类型Node.contains()事件目标

Dav*_*mes 5 javascript reactjs flowtype

我在React中有这个事件监听器:

document.removeEventListener("mouseup", this.handleDocumentClick);
Run Code Online (Sandbox Code Playgroud)

根据Flow的源代码,这是此方法的定义之一:

removeEventListener(type: MouseEventTypes, listener: MouseEventListener, optionsOrUseCapture?: EventListenerOptionsOrUseCapture): void;
Run Code Online (Sandbox Code Playgroud)

看来听众的类型必须是MouseEventListener

type MouseEventHandler = (event: MouseEvent) => mixed
type MouseEventListener = {handleEvent: MouseEventHandler} | MouseEventHandler
Run Code Online (Sandbox Code Playgroud)

所以看来我可以这样输入:

handleDocumentClick = (evt: MouseEvent) => {

}
Run Code Online (Sandbox Code Playgroud)

到目前为止,没有Flow错误。现在,我想检查事件的目标是否在我存储在React Ref中的另一个DOM节点内:

$menu: React.ElementRef<typeof Menu>;

handleDocumentClick = (evt: MouseEvent) => {
    if (this.$menu !== null) {
        const menu = ReactDOM.findDOMNode(this.$menu);

        if (menu) {
            console.log(menu.contains(evt.currentTarget));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到这个错误:

 54:                     console.log(menu.contains(evt.currentTarget));
                                                   ^^^^^^^^^^^^^^^^^ EventTarget. This type is incompatible with the expected param type of
447:   contains(other: ?Node): boolean;
                        ^^^^ Node. See lib: /private/tmp/flow/flowlib_3e761601/dom.js:447
Run Code Online (Sandbox Code Playgroud)

contains方法应适用于事件的目标(它是DOM节点)。这里可能出什么问题–也许containsin Flow 的定义?

kal*_*ley 5

您有几种选择,最简单的选择可能是:

handleDocumentClick = (evt: MouseEvent) => {
    if (this.$menu !== null) {
        const menu = ReactDOM.findDOMNode(this.$menu);

        if (menu && evt.currentTarget instanceof Node) {
            console.log(menu.contains(evt.currentTarget));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,您始终currentTarget可以强制转换(可以强制转换为Node,但您需要强制强制转换为any第一个):

handleDocumentClick = (evt: MouseEvent) => {
    if (this.$menu !== null) {
        const menu = findDOMNode(this.$menu)

        if (menu) {
            // console.log(menu.contains(((evt.currentTarget: any): Node)))
            console.log(menu.contains((evt.currentTarget: any)))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

第一个选项可以保护您,以防万一您遇到了一些奇怪的情况(而且您可以随时添加类似isNode或重复使用的实用程序功能)。