这篇文章发布于 2024年01月11日,星期四,23:01,归类于 JS实例。 阅读 12409 次, 今日 14 次 8 条评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11097 鑫空间-鑫生活
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。
一、事务繁忙,长话短说
目前主流的下拉列表,或者下拉面板的实现方式都是这样的。
点击按钮,让下拉元素显示,绝对定位,同时设置层级,点击空白处,隐藏下拉列表。
其中,每一步都需要JavaScript代码的参与,因此,一个下拉组件的JS代码量还是不容小觑的。
现在,浏览器已经支持原生popover属性,上面这种下拉列表实现方式可以扫进垃圾箱了。我可以这么说,日后使用popover属性实现下拉效果一定是主流实现方案。
因为有两个好处:
- 代码极简;
- 层级顶级;
例如有如下所示的HTML代码:
<button popovertarget="imgBook">点击显示图片</button> <img id="imgBook" popover src="/study/202312/book1.jpg" />
无需任何JS代码,点击按钮,就可以让图片显示,点击页面空白处,图片会自动隐藏,实时效果如下:
这就是上面说到的代码极简。
至于层级顶级。
这是Web中专有的一个概念,称为top-layer,元素全屏,或者<dialog>
对话框使用showModal()方法显示的时候,都会表现为top-layer,如下图所示:
顾名思意就是层级顶级,页面中任何元素都无法覆盖,哪怕z-index设置为999999。
一个页面可以有多个层级顶级元素,至于哪个在最上面,采用的是后来居上的原则,也就是那个后显示,那个就在上面,这个非常符合真实的交互需求。
基于以上两点,popover属性一定是下拉交互的最佳实现。
二、案例演示,一目了然
例如,在LuLu UI中的<select>
模拟下拉框的效果是这样的:
现在要实现此效果,极其简单,只需要让下拉框在显示的时候计算下定位就可以了(默认是浏览器居中定位的)。
HTML结构示意:
<button id="button" popovertarget="select">请选择</button> <menu id="select" popover> <li><input type="radio" name="type" value="">请选择</li> <li><input type="radio" name="type" value="1">选项1</li> <li><input type="radio" name="type" value="2">选项2</li> <li><input type="radio" name="type" value="3" disabled>选项3</li> <li><input type="radio" name="type" value="4">选项4</li> </menu>
使用radio单选框模拟选中行为,可以保持<select>
元素的表单特性。
至于显示、隐藏以及层级设置都是popover属性自动完成的,我们无需关心,因此,所有的JS代码其实就下面这一点。
button.onclick = function () { const bounding = this.getBoundingClientRect(); select.style.top = (bounding.bottom + window.pageYOffset) + 'px'; select.style.left = (bounding.left + window.pageXOffset) + 'px'; select.style.width = bounding.width + 'px'; }; select.onclick = function (event) { if (event.target.type == 'radio') { this.hidePopover(); // 选择文字内容更新 button.textContent = event.target.parentElement.textContent; } }
是不是简单到瞠目结舌,匪夷所思?
眼见为实,你可以狠狠地点击这里:使用popover属性模拟select下拉demo
下拉列表各种状态应有尽有。
三、与时俱进,勇攀高峰
popover属性目前所有现代浏览器都支持了,在不久的将来大规模应用已是大势所趋。
好了,就说这么多吧。
最近忙碌,就不扯淡了。
感谢阅读,欢迎!
本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11097
(本篇完)
- 告别JS浮层,全新的CSS Anchor Positioning锚点定位API (0.597)
- 查漏补缺,我仍未知道的HTML nonce和popover属性 (0.341)
- 复选框单选框与文字对齐问题的研究与解决 (0.156)
- 聊聊Top Layer顶层特性的隐患与实践 (0.145)
- CSS radio/checkbox单复选框元素显隐技术 (0.143)
- CSS :default伪类选择器简介 (0.143)
- CSS accent-color属性简介 (0.143)
- HTML slot 插槽元素深入 (0.103)
- CSS渐变图片背景下高度亦自适应按钮 (0.102)
- letter-spacing+first-letter实现按钮文字隐藏 (0.102)
- IE6下png背景不透明问题的综合拓展 (RANDOM - 0.013)
这种用键盘方向键没法选中菜单,对于习惯纯键盘操作不友好
不理解为什么要加上 window.pageXOffset,fixed 定位和 boundingClientRect 都是相对于视口的,如果加上 pageXOffset 反而会对不齐。
测试地址:https://codepen.io/tj-y/pen/oNVYjNY
测试时先滚动页面再点击打开 popover
因为要改成绝对定位
看来底部的“分享”按钮也可以优化成这种形式了??
估计明年就能正式用上锚点定位了,代码更少了
写了个demo玩,记得在chrome://flags/里打开Experimental Web Platform features
https://codepen.io/lunar-dark/full/zYbKgWW
这样实现还是有一个经典的下拉框元素在body内的困扰:popover的内容不会随着触发元素滚动(部分客户依然有这样的需求),这样如果再用scroll事件去补的话会很麻烦
也还好,菜单出来的时候是不让滚动的(
还必须兼容IE11的我, 一声长叹