【问题标题】:Detect whether input element is focused within ReactJS检测输入元素是否在 ReactJS 中聚焦
【发布时间】:2015-08-17 14:46:01
【问题描述】:

如何检测如下输入元素当前是否聚焦在 ReactJS 渲染函数中?

<input type="text" style={searchBoxStyle} placeholder="Search"></input>   

【问题讨论】:

    标签: javascript node.js reactjs


    【解决方案1】:

    只要输入节点已挂载且有引用,您就可以检查document.activeElement

    const searchInput = React.useRef(null)
    
    if (document.activeElement === searchInput.current) {
      // do something
    }
    
    return <input type="text" ref={searchInput} />
    

    另一种方法是在输入字段中为 focusblur 事件添加事件侦听器:

    const [focused, setFocused] = React.useState(false)
    const onFocus = () => setFocused(true)
    const onBlur = () => setFocused(false)
    
    return <input type="text" onFocus={onFocus} onBlur={onBlur} />
    

    请注意,每次节点聚焦或模糊时,这都会调用重新渲染(但这正是您想要的,对吧?)

    【讨论】:

    • findDOMNode 已移至ReactDOM
    • @JamesBrierley 谢谢!已经验证并编辑了反映 React.findDOMNode() 的答案不再存在,但可以作为 ReactDOM.findDOMNode()
    • 对于多年后发现这篇文章的任何人:在 React 16.x 及更高版本中,不再建议使用 refs 这种方式,应该使用新的 React.createRef() 功能。更多信息:reactjs.org/docs/refs-and-the-dom.html
    • 我用第二种方法解决了我的问题。显然,没有refs.current.hasFocus这样的东西
    • 我猜您将document.activeElement 与您的参考进行比较:document.activeElement === this.ref.current
    【解决方案2】:

    我从大卫给出的答案开始,他描述了两种方法,它们都对我有用,但我对这两种方法都有顾虑:

    1. 在第一种情况下,它使用findDOMNode,有一些缺点:至少不鼓励使用它,并且可以很容易地以一种被认为是反模式的方式实现;而且它还可以通过绕过虚拟DOM并直接使用DOM来使代码变慢。

    2. 在第二个选项中,创建和管理组件状态只是发现答案似乎工作量太大,很容易不同步,并且可能导致组件不必要地重新渲染。

    所以在尝试更多地探索这个问题之后,我想出了以下解决方案:

    if (this.props.id === document.activeElement.id) {
      // your code goes here
    }
    

    对大卫的回答也有同样的评论:

    您不应该在render 方法中执行此操作,因为输入节点可能尚未安装。使用像 componentDidUpdatecomponentDidMount 这样的生命周期方法。

    优点:

    • 使用当前组件属性(不可变值)
    • 不需要状态管理,因此不会导致不必要的重新渲染
    • 不需要 DOM 遍历,因此性能应该尽可能好
    • 不需要创建组件引用

    要求:

    • 您的组件应该有一个 id 属性,该属性将传递给您要检查的表单元素(无论如何,这很可能是这种情况)

    【讨论】:

      【解决方案3】:

      使用钩子:

      首先你创建并初始化你的引用

      const yourElement = useRef(null)
      

      然后你用你刚刚创建的引用标记你的元素:

      <div ref={yourElement}>Im an DOM node</div>
      

      然后,您使用此逻辑来比较 document.activeElement 文档属性是否等于您引用的 DOM 节点

      yourElement.current === document.activeElement
      

      【讨论】:

        【解决方案4】:

        使用钩子的方法要简单得多。

        进行导入

        import React, {useState} from "react";
        

        定义

        const [isMyInputFocused, setIsMyInputFocused] = useState(false);
        

        在您选择的输入中添加

                            onBlur={() => setIsMyInputFocused(false)}
                            onFocus={() => setIsMyInputFocused(true)}
        

        从现在开始,您可以随意访问isMyInputFocused

        【讨论】:

        • 这是一个“伪焦点”,无法很好地扩展:例如:如果有 10 个输入,您将不得不提升此状态并开始管理 refs,否则需要将此状态应用于每个输入并且存在不同步的风险
        • 惊人的答案谢谢。我将它用于单次使用的兄弟关系,所以这对我来说很好
        【解决方案5】:

        使用功能组件可以判断当前输入是否有焦点:

        import React from "react";
        
        export default function App() {
          const ref = React.createRef(null);
        
          const handleMouseOut = (currentRef) => {
        
            if (document.activeElement === currentRef) {
              console.log("Yesss");
            }
          };
          return (
            <div className="App">
              <input
                type="text"
                ref={ref}
                onMouseOut={() => handleMouseOut(ref.current)}
              />
            </div>
          );
        }
        

        现场示例:https://codesandbox.io/s/reverent-allen-0qr8u

        【讨论】:

          【解决方案6】:

          根据您想要做什么,您可以使用onFocus (React 17) 或 onBlur (React 16) 来实现当这些事情成为焦点时您想要的功能。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-09-11
            • 1970-01-01
            • 2018-06-26
            • 2013-08-18
            • 1970-01-01
            • 2014-01-01
            • 2023-03-27
            相关资源
            最近更新 更多