检测输入元素是不是在 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 />
另一种方法是在输入字段中为 focus
和 blur
事件添加事件侦听器:
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
方法中执行此操作,因为输入节点可能尚未安装。使用像componentDidUpdate
或componentDidMount
这样的生命周期方法。
优点:
使用当前组件属性(不可变值) 不需要状态管理,因此不会导致不必要的重新渲染 不需要 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时出现类型错误