注册
web

一篇文章告诉你 <按钮> 如何选择,div button 还是a?

前言


当你要创建一个可点击的元素时,是使用 a标签button按钮 还是 div 等其他不同的元素?


// 🚩
export function MyButton() {
return <div onClick={...}>点击我</div>
}
//❓
export function MyButton() {
return <button onClick={...}>点击我</button>
}
//❓
export function MyButton() {
return <a onClick={...}>点击我</a>
}
复制代码

出人意料的是大多数人都会选择div,这似乎与我们所学的很不一样。


这篇文章将展开对比三者的区别,并做了一个总结,这对于你工作或者面试的时候是很有帮助的。


div


让我们首先弄清楚一件事


您不应该将 div 用于可点击的元素(至少在 99% 的情况下)。


为什么?


严格上来说, div != 按钮。 div 只是一个通用容器,缺少一些可正确点击的元素应具备的特性,例如:



  • Div 不可聚焦,例如, tab 键不会像设备上的任何其他按钮那样聚焦 div。
  • 屏幕阅读器和其他辅助设备不会将 div 识别为可点击元素。
  • Div 不会将某些键输入(如空格键或返回键)转换为获得焦点时的点击。

但是,您可以使用 tabindex="0" 和 role=”button” 等几个属性解决其中一些问题:


// 🚩 试着将 div 改造成像 button一样...
export function MyButton() {
function onClick() { ... }
return (
<div
className="my-button"
tabindex="0" // 让div 能聚焦
role="button" // 屏幕阅读器和其他辅助设备 识别可点击
onClick={onClick}
onKeydown={(event) => {
// 聚焦时监听 回车键和空格键
if (event.key === "Enter" || event.key === "Space") {
onClick()
}
}}
>
点击我
</div>
)
}
复制代码

是的,我们需要确保设置聚焦状态的样式,以便用户反馈该元素也被聚焦。我们必须确保这通过了所有问题可访问性,例如:


.my-button:focus-visible {
outline: 1px solid blue;
}
复制代码

如果要还原所有细微且关键的按钮行为,并手动实现,需要大量工作。


button


The beauty of the button tag is it behaves just like any other button on your device, and is exactly what users and accessibility tools expect.

button 标签的美妙之处在于它的行为与您设备上的任何其他 button 一样,并且正是用户和辅助工具所期望的。


它是可聚焦的、可访问的、可键盘输入的,具有兼容的焦点状态样式!


// ✅
export function MyButton() {
return (
<button onClick={...}>
点击我
</button>
)
}
复制代码

有几个我们需要注意的问题。


button 的问题


我一直对按钮最大的烦恼是它们的样式


例如,给按钮一个浅紫色背景:


<button class="my-button">
Click me
</button>
<style>
/* 🤢 */
.my-button {
background-color: purple;
}
</style>
复制代码

这看起来就像 Windows 95 一样的样式。


A pretty ugly button


这就是为什么我们都喜欢 div。它们没有额外的样式或默认行为。它们的工作和外观每次都完全符合预期。


你可以说, appearance: none 会重置外观!但是这并不能完全按照您的想法进行。


<button class="my-button">
Click me
</button>
<style>
.my-button {
appearance: none; /* 🤔 */
background-color: purple;
}
</style>
复制代码

它仍然是这样:


A pretty ugly button


重置 button 的样式


没错,我们必须对每一个样式属性逐行重置:


/* ✅ */
button {
padding: 0;
border: none;
outline: none;
font: inherit;
color: inherit;
background: none
}
复制代码

这就是一个样式和行为都像 div 的按钮,它仍然使用浏览器的默认焦点样式。


您的另一种选择是使用 all: unset 恢复一个简单属性中的无特殊样式:


/* ✅ */
button { all: unset; }
button:focus-visible { outline: 1px solid var(--your-color); }
复制代码

但是不要忘记添加您自己的焦点状态;例如,您的品牌颜色的轮廓具有足够的对比度。


修复 button 行为属性


使用 button 标签时需要注意最后一个问题。


默认情况下, form 内的任何按钮都被视为提交按钮,单击时将提交表单


function MyForm() {
return (
<form onSubmit={...}>
...
<button type="submit">Submit</button>
{/* 🚩 点击 "Cancel"仍然会提交表单! */}
<button onClick={...}>Cancel</button>
</form>
)
}
复制代码

没错,按钮的默认 type 属性是 submit 。很奇怪。而且很烦人


解决此问题,除非您的按钮实际上是为了提交表单,否则请始终向其添加 type="button" ,如下所示:


export function MyButton() {
return (
<button
type="button" // ✅
onClick={...}>
Click me
</button>
)
}
复制代码

现在我们的按钮将不再尝试找到它们最接近的 form parent 并提交它。


哇,配置一个简单的按钮几乎变得奇怪了。


a标签 链接


这是大部分人也不注意的一点。我们使用按钮链接到其他页面:


// 🚩
function MyLink() {
return (
<button
type="button"
onClick={() => {
location.href = "/"
}}
>
Don't do this
</button>
)
}
复制代码

使用 点击事件 链接到页面的按钮的一些问题:



  • 它们不可抓取,因此对 SEO 非常不利。
  • 用户无法在新标签页或窗口中打开此链接;例如,右键单击在新选项卡中打开

因此,我们不要使用按钮进行导航。这就是我们需要 a 标签。


// ✅
function MyLink() {
return (
<a href="/">
Do this for links
</button>
)
}
复制代码

a 标签具有按钮的所有上述优点——可访问、可聚焦、可键盘输入——而且它们没有一堆默认的样式!


那我们是否应该将它们用于任何可点击的东西为我们自己省去一些麻烦?


// 🚩
function MyButton() {
return (
<a onClick={...}>
Do this for links
</a>
)
}
复制代码

不行


这是因为没有 href属性 的 a 标签不再像按钮一样工作。没错,当它 href 属性有值时,才有完整的按钮行为,例如可聚焦... 。


所以,我们一定要坚持使用按钮作为按钮,使用锚点作为链接。


buttona 结合起来


我非常喜欢的是将这些规则封装在一个组件中,这样你就可以只使用你的 MyButton 组件,


如果你 提供一个 URL,它就会变成一个链接,否则就是一个按钮就像这样:


// ✅
function MyButton(props) {
if (props.href) {
return <a className="my-button" {...props} />
}
return <button type="button" className="my-button" {...props} />
}

// 渲染出一个 <a href="/">
<MyButton href="/">Click me</MyButton>

// 渲染出 <button type="button">
<MyButton onClick={...}>Click me</MyButton>
复制代码

这样,无论按钮的用途是单击处理程序还是指向另一个页面的链接,我们都可以获得一致的开发人员体验和用户体验。


总结




  • 对于链接,使用带有 href 属性的 a标签,




  • 对于所有其他按钮,使用带有 type="button" 的 button 标签。




  • 需要一个点击容器,就用 div 标签


作者:前端代码王
链接:https://juejin.cn/post/7197995910566740025
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册