发布于 2026-01-06 3 阅读
0

How to create a button with a div in React (and why you shouldn't) 1. onClick handler 2. Adding a Role, tabindex 3. Keyboard events 4. Disabled state 5. Button Styles Conclusion

如何在 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>
}



Enter fullscreen mode Exit fullscreen mode

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>
}


Enter fullscreen mode Exit fullscreen mode

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>
  );
};


Enter fullscreen mode Exit fullscreen mode

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>
  );
};


Enter fullscreen mode Exit fullscreen mode

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);
}


Enter fullscreen mode Exit fullscreen mode

结论

我认为,要说明用一个按钮创建一个按钮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>
  );
};


Enter fullscreen mode Exit fullscreen mode
文章来源:https://dev.to/jakepartusch/how-to-create-a-button-with-a-div-in-react-and-why-you-shouldn-t-1743