javascript - 带有 React 的漫游 tabindex
问题描述
在 React 中制作“漫游 tabindex”的最简单方法是什么?它基本上tabindex=0/-1
是在子元素之间切换焦点。只有一个元素拥有tabindex
of 0
,而其他元素接收-1
。箭头键tabindex
在子元素之间切换,并聚焦它。
现在,我做一个所需类型的简单子映射,并设置index
prop 和 get ref
,以便以后使用。它看起来很健壮,但可能有更简单的解决方案吗?
我当前的解决方案(伪javascript,仅用于想法说明):
ElementWithFocusManagement.js
function recursivelyMapElementsOfType(children, isRequiredType, getProps) {
return Children.map(children, function(child) {
if (isValidElement(child) === false) {return child;}
if (isRequiredType(child)) {
return cloneElement(
child,
// Return new props
// {
// index, iterated in getProps closure
// focusRef, saved to `this.focusable` aswell, w/ index above
// }
getProps()
);
}
if (child.props.children) {
return cloneElement(child, {
children: recursivelyMapElementsOfType(child.props.children, isRequiredType, getProps)
});
}
return child;
});
}
export class ElementWithFocusManagement {
constructor(props) {
super(props);
// Map of all refs, that should receive focus
// {
// 0: {current: HTMLElement}
// ...
// }
this.focusable = {};
this.state = {
lastInteractionIndex: 0
};
}
handleKeyDown() {
// Handle arrow keys,
// check that element index in `this.focusable`
// update state if it is
// focus element
}
render() {
return (
<div onKeyDown={this.handleKeyDown}>
<Provider value={{lastInteractionIndex: this.state.lastInteractionIndex}}>
{recursivelyMapElementsOfType(
children,
isRequiredType, // Check for required `displayName` match
getProps(this.focusable) // Get index, and pass ref, that would be saved to `this.focusable[index]`
)}
</Provider>
</div>
);
}
}
with-focus.js
export function withFocus(WrappedComponent) {
function Focus({index, focusRef, ...props}) {
return (
<Consumer>
{({lastInteractionIndex}) => (
<WrappedComponent
{...props}
elementRef={focusRef}
tabIndex={lastInteractionIndex === index ? 0 : -1}
/>
)}
</Consumer>
);
}
// We will match for this name later
Focus.displayName = `WithFocus(${WrappedComponent.name})`;
return Focus;
}
任何东西.js
const FooWithFocus = withFocus(Foo);
<ElementWithFocusManagement> // Like toolbar, dropdown menu and etc.
<FooWithFocus>Hi there</FooWithFocus> // Button, menu item and etc.
<AnythingThatPreventSimpleMapping>
<FooWithFocus>How it's going?</FooWithFocus>
</AnythingThatPreventSimpleMapping>
<SomethingWithoutFocus />
</ElementWithFocusManagement>
解决方案
react-roving-tabindex
看起来相当不错。
推荐阅读
- regex - 应该从 URL 中省略哪些字符以使其不被编码?(即更具人类可读性)
- ios - XCODE:UIView 背景没有出现在屏幕上,即使我在情节提要中设置了颜色并以编程方式
- java - 为什么我的工作没有显示我的转移工作
- r - 在 R 中标记重复项
- authorization - 检查权利/身份验证时在哪里解析资源所有者
- ruby-on-rails - 如何在rails应用程序中提交表单数据而不重新加载页面
- javascript - 混淆 forEach() 方法中参数的使用
- reactjs - 在 ReactJs 中将搜索词更改为小写
- reactjs - 将 React 代码库移动到 TypeScript 时出现问题
- angular - 如何链接多个 ngrx 选择器?