React中管理快捷键的方法
A method to manage keyboard shortcuts in react
在 Web 应用程序中管理键盘快捷键有点棘手。
考虑一个 Widget
组件。
我希望能够根据键盘快捷键将某些元素和 运行 功能集中在该组件上。
class Widget extends React.Component {
componentDidMount() {
this.setBindings()
},
componentWillUnmount() {
this.removeBindings();
}
}
setBindings 和 removeBindings,将使用像 mousetrap 这样的库来绑定特定的键盘快捷键
现在,上述解决方案存在两个问题:
- 它使键盘快捷键行为不可预测
- 考虑挂载两个 Widget 的情况,一个会覆盖另一个
- 小部件与快捷方式紧密结合——现在如果有人不想使用快捷方式,他们必须在
Widget
上设置某种标志。这破坏了代码的 'granularity' —— 理想情况下,用户应该能够使用 Widget,然后是 WidgetWithShortcuts,或者像这样的东西
另一个可能的解决方案是传递一个实例
const widgetShortcuts = (widgetInstance) => {
return {
'ctrl i': () => widgetInstance.focusInput(),
}
}
第二种方案的问题是:
widgetInstance 将不得不公开许多可公开访问的方法,例如 focusSomeThing 或 invokeProp 等
如果Widget
想要一些工具提示,在某些地方显示键盘快捷键,关于键盘快捷键的信息将在不同的地方重复。将可以在一个地方更改快捷方式,而在另一个地方忘记这样做
关于如何通过解决上述问题来实现键盘快捷键,是否有最佳实践或一些想法?
我认为最好的办法是在顶层设置一次键盘快捷键侦听器,然后将信息传递给可能关心或不关心快捷方式发生的组件。这解决了问题 1,您可以多次绑定侦听器,并且这也排除了暴露任何组件功能的需要。
class ShortcutProvider extends Component {
state = { shortcut: null }
componentDidMount() {
// shortcut library listener
onShortcut(shortcut => this.setState({ shortcut })
}
render() {
<App shortcut={this.state.shortcut} />
}
}
然后您的小部件可以对道具更改做出反应(或不做出反应):
class Widget extends Component {
...
componentWillReceiveProps(nextProps) {
if (this.state.shouldReactToShortcut) {
if (nextProps.shortcut === 'ctrl i') {
// do something
}
}
}
...
}
如果您要将快捷方式属性传递给许多组件,那么将快捷方式状态放入上下文中可能是值得的。
React-hotkeys 不是一种方法,而是一种听起来可以解决您面临的问题的工具。
一些注意事项:
- 您可以通过将组件包装在附加了热键的自定义
<HotKeys>
组件中来使用它。
- 方法不是 public,而是通过
keymap
& handler
分配给热键
- 添加到子组件的热键将优先于父组件的热键
这个插件的一个 issue I'm facing 是似乎没有办法阻止在输入字段中键入时触发热键,但除此之外它似乎工作得很好。
在 Web 应用程序中管理键盘快捷键有点棘手。
考虑一个 Widget
组件。
我希望能够根据键盘快捷键将某些元素和 运行 功能集中在该组件上。
class Widget extends React.Component {
componentDidMount() {
this.setBindings()
},
componentWillUnmount() {
this.removeBindings();
}
}
setBindings 和 removeBindings,将使用像 mousetrap 这样的库来绑定特定的键盘快捷键
现在,上述解决方案存在两个问题:
- 它使键盘快捷键行为不可预测
- 考虑挂载两个 Widget 的情况,一个会覆盖另一个
- 小部件与快捷方式紧密结合——现在如果有人不想使用快捷方式,他们必须在
Widget
上设置某种标志。这破坏了代码的 'granularity' —— 理想情况下,用户应该能够使用 Widget,然后是 WidgetWithShortcuts,或者像这样的东西
另一个可能的解决方案是传递一个实例
const widgetShortcuts = (widgetInstance) => {
return {
'ctrl i': () => widgetInstance.focusInput(),
}
}
第二种方案的问题是:
widgetInstance 将不得不公开许多可公开访问的方法,例如 focusSomeThing 或 invokeProp 等
如果
Widget
想要一些工具提示,在某些地方显示键盘快捷键,关于键盘快捷键的信息将在不同的地方重复。将可以在一个地方更改快捷方式,而在另一个地方忘记这样做
关于如何通过解决上述问题来实现键盘快捷键,是否有最佳实践或一些想法?
我认为最好的办法是在顶层设置一次键盘快捷键侦听器,然后将信息传递给可能关心或不关心快捷方式发生的组件。这解决了问题 1,您可以多次绑定侦听器,并且这也排除了暴露任何组件功能的需要。
class ShortcutProvider extends Component {
state = { shortcut: null }
componentDidMount() {
// shortcut library listener
onShortcut(shortcut => this.setState({ shortcut })
}
render() {
<App shortcut={this.state.shortcut} />
}
}
然后您的小部件可以对道具更改做出反应(或不做出反应):
class Widget extends Component {
...
componentWillReceiveProps(nextProps) {
if (this.state.shouldReactToShortcut) {
if (nextProps.shortcut === 'ctrl i') {
// do something
}
}
}
...
}
如果您要将快捷方式属性传递给许多组件,那么将快捷方式状态放入上下文中可能是值得的。
React-hotkeys 不是一种方法,而是一种听起来可以解决您面临的问题的工具。
一些注意事项:
- 您可以通过将组件包装在附加了热键的自定义
<HotKeys>
组件中来使用它。 - 方法不是 public,而是通过
keymap
&handler
分配给热键
- 添加到子组件的热键将优先于父组件的热键
这个插件的一个 issue I'm facing 是似乎没有办法阻止在输入字段中键入时触发热键,但除此之外它似乎工作得很好。