如何处理两个特定元素之间的焦点变化
How to handle change of focus between two specific elements
我有两个(或更多)HTML 元素,我想在其中任何一个失去焦点时执行回调,除非焦点在它们之间移动。换句话说,我想从焦点的角度将这些元素视为一个元素并执行 group-onBlur
回调。
使用 React 我试图跟踪每个元素在状态上的焦点,但是当将焦点从元素 a
移动到元素 b
时,onBlur
在 a
总是在 b
上的 onFocus
之前发生。此外,由于状态更新可能是异步的,我不确定状态的一致性。
通常情况下,您会在超时后将其关闭并等待几毫秒,然后再触发文本步骤。快速而肮脏的反应代码。
class Test extends React.Component {
constructor(props) {
super(props)
this.state = {
blurTimer: null
}
this.handleBlur = this.handleBlur.bind(this);
this.handleFocus = this.handleFocus.bind(this);
}
clearTimer() {
if (this.state.blurTimer) {
window.clearTimeout(this.state.blurTimer);
this.setState({ blurTimer: null });
}
}
processIt() {
console.log('Process it!!!!');
}
handleBlur() {
this.clearTimer();
const blurTimer = window.setTimeout(() => this.processIt(), 100);
this.setState({ blurTimer });
}
handleFocus() {
this.clearTimer();
}
render() {
return (
<div>
<h2>foo</h2>
<input type="text" onBlur={this.handleBlur} onFocus={this.handleFocus} />
<input type="text" onBlur={this.handleBlur} onFocus={this.handleFocus} />
</div>
)
}
}
ReactDOM.render(<Test />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
您可以存储对每个要“共享”焦点的输入的引用,然后在采取任何操作之前检查是否有任何一个焦点在您的 onBlur
函数中。但是请注意,如果您在模糊发生时立即检查,聚焦元素是 body
。要解决此问题,您可以将 onBlur
逻辑包装在延迟 0
毫秒的 setTimeout
调用中。
这是一个例子:
function MyComponent() {
const aRef = React.useRef(null);
const bRef = React.useRef(null);
function onBlurGroup() {
window.setTimeout(() => {
if (document.activeElement === aRef.current || document.activeElement === bRef.current) {
console.log("a or b is focused");
return;
}
console.log("focus lost from group");
// do blur handling
}, 0)
}
return (
<div>
<input ref={aRef} name="a" type="text" onBlur={onBlurGroup}/>
<input ref={bRef} name="b" type="text" onBlur={onBlurGroup}/>
<input name="other" type="text"/>
</div>
);
}
和一个功能示例(使用基于 class 的组件,因为 Stack 尚不支持挂钩):
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.aRef = React.createRef();
this.bRef = React.createRef();
}
onBlurGroup = () => {
window.setTimeout(() => {
if (document.activeElement === this.aRef.current || document.activeElement === this.bRef.current) {
console.log("a or b is focused");
return;
}
console.log("focus lost from group");
// do stuff
}, 0)
}
render() {
return (
<div>
<input ref={this.aRef} name="a" placeholder="A" type="text" onBlur={this.onBlurGroup}/>
<input ref={this.bRef} name="b" placeholder="B" type="text" onBlur={this.onBlurGroup}/>
<input name="other" placeholder="Other" type="text"/>
</div>
);
}
}
ReactDOM.render(<MyComponent/>, document.querySelector("#root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
我有两个(或更多)HTML 元素,我想在其中任何一个失去焦点时执行回调,除非焦点在它们之间移动。换句话说,我想从焦点的角度将这些元素视为一个元素并执行 group-onBlur
回调。
使用 React 我试图跟踪每个元素在状态上的焦点,但是当将焦点从元素 a
移动到元素 b
时,onBlur
在 a
总是在 b
上的 onFocus
之前发生。此外,由于状态更新可能是异步的,我不确定状态的一致性。
通常情况下,您会在超时后将其关闭并等待几毫秒,然后再触发文本步骤。快速而肮脏的反应代码。
class Test extends React.Component {
constructor(props) {
super(props)
this.state = {
blurTimer: null
}
this.handleBlur = this.handleBlur.bind(this);
this.handleFocus = this.handleFocus.bind(this);
}
clearTimer() {
if (this.state.blurTimer) {
window.clearTimeout(this.state.blurTimer);
this.setState({ blurTimer: null });
}
}
processIt() {
console.log('Process it!!!!');
}
handleBlur() {
this.clearTimer();
const blurTimer = window.setTimeout(() => this.processIt(), 100);
this.setState({ blurTimer });
}
handleFocus() {
this.clearTimer();
}
render() {
return (
<div>
<h2>foo</h2>
<input type="text" onBlur={this.handleBlur} onFocus={this.handleFocus} />
<input type="text" onBlur={this.handleBlur} onFocus={this.handleFocus} />
</div>
)
}
}
ReactDOM.render(<Test />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
您可以存储对每个要“共享”焦点的输入的引用,然后在采取任何操作之前检查是否有任何一个焦点在您的 onBlur
函数中。但是请注意,如果您在模糊发生时立即检查,聚焦元素是 body
。要解决此问题,您可以将 onBlur
逻辑包装在延迟 0
毫秒的 setTimeout
调用中。
这是一个例子:
function MyComponent() {
const aRef = React.useRef(null);
const bRef = React.useRef(null);
function onBlurGroup() {
window.setTimeout(() => {
if (document.activeElement === aRef.current || document.activeElement === bRef.current) {
console.log("a or b is focused");
return;
}
console.log("focus lost from group");
// do blur handling
}, 0)
}
return (
<div>
<input ref={aRef} name="a" type="text" onBlur={onBlurGroup}/>
<input ref={bRef} name="b" type="text" onBlur={onBlurGroup}/>
<input name="other" type="text"/>
</div>
);
}
和一个功能示例(使用基于 class 的组件,因为 Stack 尚不支持挂钩):
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.aRef = React.createRef();
this.bRef = React.createRef();
}
onBlurGroup = () => {
window.setTimeout(() => {
if (document.activeElement === this.aRef.current || document.activeElement === this.bRef.current) {
console.log("a or b is focused");
return;
}
console.log("focus lost from group");
// do stuff
}, 0)
}
render() {
return (
<div>
<input ref={this.aRef} name="a" placeholder="A" type="text" onBlur={this.onBlurGroup}/>
<input ref={this.bRef} name="b" placeholder="B" type="text" onBlur={this.onBlurGroup}/>
<input name="other" placeholder="Other" type="text"/>
</div>
);
}
}
ReactDOM.render(<MyComponent/>, document.querySelector("#root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"/>