如何在 React 中使用 div 创建按钮(以及为什么不应该这样做)
1. onClick 处理程序
2. 添加角色,tabindex
3. 键盘事件
4. 禁用状态
5. 按钮样式
结论
作为Web开发人员,我们经常需要创建Web应用程序中的各种交互式组件。有时,向现有组件添加点击处理程序div,或者<Button/>使用非语义元素创建自定义组件,似乎是一个很诱人的解决方案。
在本文中,我希望阐明不使用按钮而产生的“隐藏”错误button,以及克服这些缺陷所需的代码量。
1. onClick 处理程序
这是为元素添加交互的显而易见的第一步div。但是,顾名思义,onClick元素上的事件处理程序div仅支持鼠标点击事件(onClick而带有事件处理程序button的功能则更多)。遗憾的是,仅支持鼠标事件会让键盘用户和屏幕阅读器用户感到困惑。他们无法得知元素已成为可操作元素,也无法通过键盘触发交互。
//DO NOT USE: non-accessible implementation
const Button = () => {
const onClick = () => console.log('clicked');
return <div onClick={onClick}>My Button</div>
}
2. 添加角色,tabindex
我们可以通过给 `<div>` 添加 ` tabindex`和 `role` 属性来逐步实现一个易于访问的解决方案div。`role`属性会告诉屏幕阅读器将此元素读作按钮,并提示它是可操作的。在 React 中设置tabindex="0"` tabindex` 属性tabIndex={0},可以让键盘聚焦到此元素上。即便如此,我们的自定义按钮div仍然无法被键盘触发。
//DO NOT USE: non-accessible implementation
const Button = () => {
const onClick = () => console.log('clicked');
return <div role="button" tabIndex={0} onClick={onClick}>My Button</div>
}
3. 键盘事件
当按钮获得焦点时,可以通过快捷键或事件button触发。为了实现按钮的此功能,我们需要实现并监听这些特定事件。然后,我们可以手动将匹配的事件转发给我们的处理程序。SPACEENTERdivonKeyPressonClick
通过实施这前三个步骤,我们的div按钮现在基本可以访问了。
const Button = () => {
const onClick = () => console.log("clicked");
const onKeyPress = e => {
const enterOrSpace =
e.key === "Enter" ||
e.key === " " ||
e.key === "Spacebar" ||
e.which === 13 ||
e.which === 32;
if (enterOrSpace) {
e.preventDefault();
onClick(e);
}
};
return (
<div
role="button"
onClick={onClick}
tabIndex={0}
onKeyPress={onKeyPress}
>
My Button
</div>
);
};
4. 禁用状态
通常情况下,该disabled属性用于阻止用户与按钮进行交互。我们可以通过将按钮的属性设置为(这将使按钮失去键盘焦点)并在按钮禁用时忽略处理程序中的任何点击事件,从而为按钮button添加相同的功能。divtabindex-1onClick
const Button = ({ disabled }) => {
const onClick = () => {
if (disabled) {
return;
}
console.log("clicked");
};
const onKeyPress = e => {
const enterOrSpace =
e.key === "Enter" ||
e.key === " " ||
e.key === "Spacebar" ||
e.which === 13 ||
e.which === 32;
if (enterOrSpace) {
e.preventDefault();
onClick(e);
}
};
return (
<div
className={disabled ? "btn disabled" : "btn"}
role="button"
tabIndex={disabled ? -1 : 0}
onClick={onClick}
onKeyPress={onKeyPress}
>
My div Button
</div>
);
};
5. 按钮样式
如果我们也想让我们的样式div看起来像,button我们可以从 Chrome 窃取默认样式(不推荐)。
//DO NOT USE: browser-specific styles
.btn {
display: inline-block;
-webkit-appearance: button;
padding: 1px 7px 2px;
cursor: default;
font: 400 11px system-ui;
color: buttontext;
background-color: buttonface;
}
.btn.disabled {
color: rgb(170, 170, 170);
}
结论
我认为,要说明用一个按钮创建一个按钮div和使用一个实际的 button按钮之间的区别,最简单的方法是用以下代码片段展示实现上述所有操作(以及更多操作)所需的代码量button。
// PLEASE USE: most accessible solution
const Button = props => {
const onClick = () => {
console.log("clicked");
};
return (
<button
onClick={onClick}
{...props}
>
My button Button
</button>
);
};