随着前端交互需求的不断增加,下拉框作为常见的UI组件之一,在多种场景中得到了广泛的应用。但是,由于业务复杂度的提升,部分场景需要实现一些特殊的下拉框组件,比如多级联动的下拉框、下拉框的宽度高度可变化、下拉框需要自定义样式等。这些特殊的需求,往往需要我们自己定制组件,而Web Components 和 shadow DOM 的出现,使得我们更加容易实现复杂的UI组件和更好的进行组件重用。
Web Components 和 shadow DOM
Web Components 是一种标准化的组件实现方式,它可以形成一套独立的自定义组件库,每个组件自包含其样式和代码,完全独立维护,不与其他组件产生影响。Web Components 内置了三个标准技术:
- Custom Elements —— 自定义元素:以前,我们只能使用内置元素来构建 UI,现在,我们可以通过定义自定义元素来创建新的 UI 组件。
- Shadow DOM —— 影子 DOM:在 Web Components 内部,我们可以使用 Shadow DOM 构建一些样式和行为的封装,Shadow DOM 会将这些封装性的内容与页面其他内容分离。
- HTML Templates —— HTML 模板:我们可以使用 HTML 模板作为自定义元素的内容,这在设计 Web Components 组件时非常有用。
以上三个技术化解了原先组件重用,维护和生命周期的繁琐性,使得 Web Components 实现更加便捷。
实现一个复杂下拉框组件
Web Components 和 shadow DOM 的出现,为实现复杂下拉框组件提供了更好的方法,下面我们针对特殊需求,实现一个复杂下拉框组件。
我们需要达到两个目的:
- 多级联动的下拉框;
- 下拉框的宽度高度可变化;
步骤一:创建自定义元素
我们首先创建一个继承自 HTMLElement 的下拉框类 SelectBox,这个类负责在页面中创建自定义元素 <select-box>,使用交互组件的时候:
<html> <head> <script src="./SelectBox.js"></script> </head> <body> <select-box></select-box> </body> </html>
是我们需要的唯一代码。
步骤二:添加 Shadow DOM
我们在自定义元素内部,添加 Shadow DOM,同时,向 Shadow DOM 中添加 HTML 模板和样式,如下:
-- -------------------- ---- ------- ------------------- - ----- ---------- - ------------------- ----- ------ --- ----- -------- - ----------------------------------- ------------------ - - ------- -- ---- ------ ---- -- -------- ---- ------------------------- ---- ----------------------------- ---- ---------------------- ------ ---- ---------------------- ---- ------------------------------------- ------ -- --------------------------------------------------------- -- ---- ---- ---- -
这里我们简单定义下组件的结构:
.select-container
为下拉框的外层容器,使用flex
实现布局;.selected-value
为展示当前选中选项的容器;.chevron
为下拉箭头,用于点击后展开下拉菜单;.dropdown-menu
为下拉菜单容器,初始状态下隐藏;.dropdown-menu__wrapper
为下拉菜单项容器。
步骤三:添加交互逻辑
这里我们在自定义元素内部添加下发交互逻辑,包括初始化、渲染选项、下拉框样式控制等操作,如下:
-- -------------------- ---- ------- ------------------- - -- ---- ---- ---- -- --- --------------------------------- ----- --------------- - --------------------------------------------------- ----------------------------------------- ------- -- - ----- ------ - -------------------------- -- -------- - ----------------------------- - ---- - ------------------------- ---- - --- ----- ------------ - --------------------------------------------------------- -------------------------------------- ------- -- - ----- ------ - ------------- -- ---------------------------------------------------- - ------------------ - ----------------- ----------------------------- ---------------------- --------------------- - ------- - -------------- ------------------- -- ---- - ---- -- ------- - -- ------- - --- ---------------------------------- ------- -- - ----- ------ - ------------- -- ------- --- --------------- -- --------------------------------- -- ------ --- ------------ -- ------------------------------- - ----------------------------- - --- -
这里关键点主要有:
- 使用
renderOptions
方法,渲染下拉菜单项; - 使用
setAttribute
、removeAttribute
开关下拉菜单状态; - 通过判断事件源 target 的 type,找到对应的点击处理内容。
一些细节内容,可以看下完整组件代码。
示例代码
下面是组件的完整代码:
-- -------------------- ---- ------- ----- --------- ------- ----------- - ------ --- -------------------- - ------ -------------------- - ------------- - -------- ------------ - --- ------------------- - --- ------------------ - -- - --- --------------- - ------ -------------------------------------- - --- - --- ----------------------- - -------------------------------------- - -- - --------- ----- --------------- - ------------------------------------------------- ------------------------- - --------- - ------------------- - ----- ---------- - ------------------- ----- ------ --- ----- -------- - ----------------------------------- ------------------ - - ------- ----------------- - ------- --- ----- ----- -------- ----- -------------- ---- -------- ----- ------------ ------- ---------------- -------------- - --------------- - ----- -- - -------- - ------ -- ------- -- ------- --- ----- ------------ ----------- --- ----- ----- ------------ ---- - -------------- - --------- --------- -------- ---- ----------- ------ ----------- ----- ----------- --- --- --- --------------- ----------------- ----- - ----------------------- - ------ ----- - ---------------------- - -------- ------ -------- ----- ------- -------- - ---------------------------- - ----------------- -------- - --------------------- - ------------- ----- - ---------------------- - -------- ----- - ----------------------------- - -------- ------ - -------- ---- ------------------------- ---- ----------------------------- ---- ---------------------- ------ ---- ---------------------- ---- ------------------------------------- ------ -- --------------------------------------------------------- --------------------------------- ----- --------------- - --------------------------------------------------- ----------------------------------------- ------- -- - ----- ------ - -------------------------- -- -------- - ----------------------------- - ---- - ------------------------- ---- - --- ----- ------------ - --------------------------------------------------------- -------------------------------------- ------- -- - ----- ------ - ------------- -- ---------------------------------------------------- - ------------------ - ----------------- ----------------------------- ---------------------- --------------------- - ------- - -------------- ------------------- -- ---- - ---- -- ------- - -- ------- - --- ---------------------------------- ------- -- - ----- ------ - ------------- -- ------- --- --------------- -- --------------------------------- -- ------ --- ------------ -- ------------------------------- - ----------------------------- - --- - --- --------------- - ----- ------------ - --- ----- --------- - ------------------------------------- -- ------------ - ------ ------------- - ---- - ------ ---------------------- - - --- ----------------------- - -- ------------------- --- --------- - ------------------------------------ -------------------------- - - ------------------------------ --------- --------- - ------ ------ - ---- ------------------ ------------ - --------------------- ------ - - ---------------------- - ----- ------------------- - --------------------------------------------------------- ----------------------------- - --- ----- ------------- - ---------------------------------- ------------------------------ -- - ---------------------------------------- --- - ---------------------------------- - ----- ------- - -------------------------- -- - ----- -- - ------------------------------ ------------------------------------------ ------------ - ------------ -- ---------------- -- ---------------------- - -- - ----- --------------- - ------------------------------ ----------------------------------------------------- ------------------------- -------------------------- - ---------- ----- ------------ - ----------------------------------------- ---------------------------------- -- - ----------------------------------------- --- -------------------------------- - ------ --- --- ------ -------- - -------------------------------- - ----- ------- - ------------------------- -- - ----- -- - ------------------------------ ------------------------------------------ ------------ - ------------ -- ---------------- -- ---------------------- - -- - ----- --------------- - ------------------------------ ----------------------------------------------------- ------------------------- -------------------------- - ---------- ----- ------------ - ----------------------------------------- ---------------------------------- -- - ----------------------------------------- --- -------------------------------- - ------ --- --- ------ -------- - - ----------------------------------- -----------
总结
本文通过介绍 Web Components 和 shadow DOM,实现了一个复杂下拉框组件的示例。Web Components 和 shadow DOM 的出现,为实现组件复用,组件设计,样式隔离和更好的SEO 提供了便利,有着很多实际应用场景,比如在 DashBoard、只含前端发布物的工程中甚至可以成为统一的组件设计标准。
如果你有更多 Web Components 的设想或实际项目中的应用,原作者非常期待你能够将你的应用与经验分享给我们。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64f7c644f6b2d6eab3ff675e