隨著前端網頁框架的 React, Vue 和 Angular 佔據主流市場後,便想找個工具來撰寫共用於這三個框架的網頁元件。看著 Svelte 的介紹以及語法對於 React 和 Vue3 的使用者友善的情況下,便參考了 前端框架 Svelte 上手指南:從基本介紹到 UI 實戰與測試(iT邦幫忙鐵人賽系列書)的內文試做一個 下拉組合方塊 ( Combo Box )。
重點摘要
A11N
皆需自行實作。role=”combobox” 會必須要搭配 aria-autocomplete、aria-controls (與選項 id 對應)、aria-expanded (選項是否打開)
另外可以多補上 aria-activedescendant (目前選中哪一個)、aria-setsize ( 總共有幾個選項)、aria-posinset (目前選中第幾個)
滑鼠控制
由於 click 事件會在 blur 之後才發生,為了避免無法正常觸發,改用比 blur 更早發生的 mousedown 來實作點擊後的效果更佳。
鍵盤控制
ArrowUp 和 ArrowDown 可以用 dom.scrollIntoView() 來處理。
await tick() 是必須的,否則會事件會卡在 CallStack 中而沒有執行,進而無法更新畫面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
case 'ArrowUp': forKeyboard.selectedIndex !== -1 ? forKeyboard.selectedIndex = (forKeyboard.selectedIndex - 1) % filteredData.length : forKeyboard.selectedIndex = (forKeyboard.selectedIndex - 1) % filteredData.length if (forKeyboard.selectedIndex <= -1) { forKeyboard.selectedIndex = filteredData.length - 1 } await tick() if (dropdownDOM) { const active = dropdownDOM.querySelector('[data-selected="true"]') if (active) { if (forKeyboard.selectedIndex === filteredData.length - 1) { active.scrollIntoView() return } if ((active.offsetTop % dropdownDOM.offsetHeight) - dropdownDOM.offsetHeight < dropdownDOM.scrollTop) { active.scrollIntoView() } } } break case 'ArrowDown': forKeyboard.selectedIndex !== -1 ? forKeyboard.selectedIndex = (forKeyboard.selectedIndex + 1) % filteredData.length : forKeyboard.selectedIndex = 0 await tick() if (dropdownDOM) { const active = dropdownDOM.querySelector('[data-selected="true"]') if (active) { if (forKeyboard.selectedIndex === 0) { active.scrollIntoView() return } if ((active.offsetTop % dropdownDOM.offsetHeight) + active.clientHeight > dropdownDOM.scrollTop + dropdownDOM.offsetHeight) { active.scrollIntoView() } } } break } |
程式碼
[ Repo ]:https://github.com/andy922200/svelte-combo-box
參考資料
1. Svelte Custom element API
2. 用svelte.js开发web components
3. Web Components with Svelte
4. How to Create Svelte Component Libraries with SvelteKit
5. Svelte — 是什麼讓我遇見這樣的你