## What does role="button" mean ? 最近在寫 `React Styled Component`,有一個需求是 `ListItem` 本身可以點擊事件,及`ListItem`裡頭的 Button 也能被點擊事件,那時也沒多想就很單純使用`Button` 包 `Button` 去解決。 ```javascript= const ListItem = () => { const click1 = () => { console.log("click1"); }; const click2 = () => { console.log("click2"); }; return ( <button onClick={click1}> <button onClick={click2}>This is a Button</button> </button> ); } ``` --- ### #Event Bubbling(冒泡事件) 那在這時我們會遇到第一個很經典的問題就是 [Event Bubbling(冒泡事件)](http://www.java2s.com/Book/JavaScript/DOM/Event_Flow_capture_target_and_bubbling.htm),這裡我們多添加 `event.stopPropagation` 即可防止冒泡,不多做其他討論。 ```javascript= const click1 = (e) => { e.stopPropagation(); console.log("click1"); };... ``` --- ### #Warning: validateDOMNesting(...): <button> cannot appear as a descendant of <button> 原本以為這樣就沒事了,但有遇到一個額外的問題 ![image](https://hackmd.io/_uploads/rJUdA7GxJl.png) 這是 HTML 規範不允許一個 <button> 元素內部再嵌套另一個 <button> 元素。React 會檢查這樣的結構並給出警告。 > 為此我們的解法是將原有 `<button>` 改為 `<div>` 並使用為 `role='button'` 屬性去符合規範,這樣就能避免上述的錯誤,而且也能繼續使用其他屬性。 --- ### #而 role="button" 解決了什麼問題 ? HTML 屬性 role 是一種用於 [ WAI-ARIA(Web Accessibility Initiative - Accessible Rich Internet Applications)](https://developer.mozilla.org/zh-TW/docs/Learn/Accessibility/WAI-ARIA_basics) 規範和標籤語義化(Semantic HTML)語意化標籤的工具,主要用於告訴輔助技術(如螢幕)元素的功能或用途。 - **提供語義化信息**:在某些情況下,HTML 元素的語義不夠明確。例如,使用 `<div>` 或 `<span>` 元素時,這些元素本身並不帶有任何語義,開發者可以使用 role 屬性明確其目的,例如 `role="button"` 或 `role="navigation"`,讓輔助技術能夠正確理解這些元素的功能。 - **提高無障礙性**:透過為元素添加 role 屬性,開發者可以幫助視力障礙用戶更好地與網頁互動。例如,將一個自定義的按鈕元素標記為 `role="button"`,使得螢幕閱讀器能告訴用戶這是一個可點擊的按鈕。 - **增強互動性**:對於使用 JavaScript 動態生成的內容,role 屬性能告訴輔助技術該元素的互動方式,例如使用 `role="alert"` 來告知用戶有新的消息或提示。 #### 以下是一些其他常見的 role 屬性及其用途: - role="button":表示一個可點擊的按鈕。 - role="link":表示一個超連結。 - role="navigation":表示導航區域。 - role="alert":表示需要立即關注的重要信息。 - role="dialog":表示一個對話框或模態窗口。 ### # 修改後的 Poo Poo Code ```javascript= const TestBtn1 = styled.div` width: 200px; height: 200px; background: gray; `; const TestBtn2 = styled.button` width: 100px; height: 100px; `; const ListItem = () => { const click1 = (e) => { e.stopPropagation(); console.log("click1"); }; const click2 = (e) => { e.stopPropagation(); console.log("click2"); }; return ( <TestBtn1 role="button" onClick={click1}> <TestBtn2 onClick={click2}>This is a Button</TestBtn2> </TestBtn1> ); } ```