检测输入元素是不是在 ReactJS 中聚焦

Posted

技术标签:

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

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

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

【问题讨论】:

【参考方案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】:

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

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

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

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

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) 来实现当这些事情成为焦点时您想要的功能。

【讨论】:

以上是关于检测输入元素是不是在 ReactJS 中聚焦的主要内容,如果未能解决你的问题,请参考以下文章

将输入字段聚焦在React组件中 - 尝试创建ref时出现类型错误

聚焦时如何使用 Reactjs 选择输入中的所有文本?

如何在 reactjs 中检测媒体是不是正在播放或是不是可能?

js元素聚焦(vue)

ReactJS:处理空间导航(键盘和游戏手柄)[关闭]

Javascript / jQuery检测输入是不是集中[重复]