提到 popover,原生于相信大家都很熟悉,原生于没错,原生于就是原生于组件库里经常见到的悬浮层(或者叫“气泡卡片”),比如 Ant Design。原生于
现在,原生于这个好用的原生于特性终于要在Chrome 114上正式支持了~下面花几分钟快速了解一下吧。
其实这个名称以前叫做popup,原生于后来才更改成了popover😂。原生于
popover是原生于一个全局属性。给任意元素添加popover以后,它就变成了一个悬浮层。
<div popover>我是悬浮层</div>
popover有两个值,分别是:
<div popover>我是悬浮层</div><div popover="auto">我是悬浮层</div><div popover="manual">我是悬浮层</div>
悬浮层默认是隐藏的,也不能通过属性设置默认显示。那么,如何打开一个悬浮层呢?
控制悬浮层有两种方式,分别是 声明式 和 命令式。
首先来看声明式,经常写原生HTML的应该会很喜欢这种方式,无需 JS 介入就可以实现悬浮层的打开和关闭,如下:
<button popovertarget="pop1">打开 auto 悬浮层</button><div id="pop1" popover>我是 auto 悬浮层</div>
只需要通过popovertarget属性将目标悬浮层的id属性和按钮相关联就行了(注意,只能是ID),效果如下:
还可以通过popovertargetaction属性来设置点击行为,有三个值,分别是:
<button popovertarget="pop1" popovertargetaction="show">打开 auto 悬浮层</button><button popovertarget="pop1" popovertargetaction="hide">关闭 auto 悬浮层</button><button popovertarget="pop1" popovertargetaction="toggle">切换 auto 悬浮层</button><div id="pop1" popover>我是 auto 悬浮层</div>
效果如下:
现在回过头来看看两种popover的区别。
<button popovertarget="pop1">切换 auto 悬浮层</button><button popovertarget="pop2">切换 manual 悬浮层</button><div id="pop1" popover>我是 auto 悬浮层</div><div id="pop2" popover="manual">我是 manual 悬浮层</div>
效果如下:
可以看到,auto悬浮层点击空白会自动关闭(还可以通过Esc键关闭),而manual悬浮层只能手动去关闭。当然大部分情况下auto可以满足需求。
所谓“命令式”,其实就是一套JS API,需要在 JS中主动去调用。
那么,有了声明式为啥还要命令式呢?答案是,更灵活。
比如,前面的声明式,只适用于click场景,如果需要hover也能打开悬浮层,这种方式就不行了。像这种情况,就可以采用命令式方式了。
先看语法,很简单,就是 3 个方法。
popoverEl.showPopover(); // 打开popoverEl.hidePopover(); // 关闭popoverEl.togglePopover(force) // 切换,可传参数,强制设置为 true 或者 false
需要注意的是,这 3 个方式仅适用于悬浮层,也就是必须有popover属性,如果是普通元素,会直接报错,如下:
还有一种情况,如果一个本来已经打开的悬浮层,再次调用showPopover(),也会报错,反之亦然
因此,在使用 JS 控制时,推荐使用manual悬浮层,便于精准控制。
下面来看一个hover控制的例子。
<button id="button">hover 打开悬浮层</button><div id="pop" popover="manual">我是 hover 悬浮层</div>
然后是相关JS。
button.addEventListener('mouseenter', () => { pop.showPopover()})button.addEventListener('mouseleave', () => { pop.hidePopover()})
效果如下:
首先,从HTML结构上来看,打开和关闭没有任何属性变化,这个和details不一样(details会添加open属性)。为此,CSS 还专门出了一个伪类:open用于标识悬浮层的打开状态。
目前还不稳定,后续可能会更变为:popover-open。
div /* 打开样式 */}
通过这个伪类,我们可以很轻松的给悬浮层添加过渡动画。
[popover]{ display: block; /*默认是display:none,不会有动画*/ visibility: hidden; opacity: 0; transform: scale(.6); transition: .3s;}[popover]:open{ visibility: visible; transform: scale(1); opacity: 1;}
效果如下:
除了 CSS 方式,JS 也能判断悬浮层的状态,但是并不是自己想象的那样。
起初,我以为有一个属性可以直接获取到悬浮层的状态,发现并不行,如下:
popoverEl.open // undefined
那如何获取呢?
其实可以借助前面 CSS 的方式,只要匹配的:open伪类不就可以了吗,需要用到matches方法。
https://developer.mozilla.org/en-US/docs/Web/API/Element/matches。
这样就能随时获取到悬浮层的打开状态了
popoverEl.matches(':open')
另外,还可以通过事件监听的方式来获取,需要用到新的事件toggle,这是一个专门针对popover新推出的事件,使用方式如下:
popoverEl.addEventListener("toggle", (event) => { if (event.newState === "open") { console.log("打开状态"); } else { console.log("关闭状态"); }});
前面说了那么多,好像并没有什么很厉害的地方,随便一个 div 都可以模拟,而且现在的组件库不是也实现的好好的吗?到底有什么优势呢?
打开控制台可以看到,popover上有一个很特殊的标识。
这个就是顶层 top-layer !也就是层级是最高的,高于页面上的一切。
这也是悬浮层的意义所在,本身就应该是悬浮在最上面。下面是示意图
这样的好处就是无论在 HTML中的任何位置,都无需担心悬浮层被遮挡的情况,也无需将悬浮层移动的最外层body上。
以上完整代码可以查看以下任意链接:
如果浏览器不支持,会有下面提示:
这个是用@supports实现的。
@supports selector([popover]:open) { .no-support{ display: none !important; }}
看一下兼容性,目前只有Chrome 114+支持,内部项目可以尝鲜一下,如果是Electron应用,那就大胆使用吧。
下面来总结一下本文要点:
最近正在对xy-ui[4]进行升级改造,里面的 popover 组件就使用到了这一特性,不过也对不支持的浏览器做了兼容,有兴趣的可以去体验一下。
https://xy-ui.codelabo.cn/components/popover。
[1]popover (juejin.cn): https://code.juejin.cn/pen/7229985240335269943。
[2]popover (codepen.io): https://codepen.io/xboxyan/pen/MWPrRod。
[3]popover (runjs.work): https://runjs.work/projects/d38b9c37b0d04897。
[4]xy-ui: https://github.com/XboxYan/xy-ui。
责任编辑:姜华 来源: 前端侦探 popover控制悬浮层(责任编辑:娱乐)
1月浙江新设外商投资企业287家 实际使用外资规模居全国第五
越南陆上风电项目葱龙乡155兆瓦风机吊装完成 预计年发电量达9亿千瓦时
帅丰电器(605336.SH)拟推176.25万股限制性股票激励计划 授予价格为13.62元/股
宁德时代拟向特定对象增发募资不超过582亿元 是利好还是利空
北上资金上周净买入9亿元 计算机、纺织服装行业连续六周获加仓
中国擎天软件(01297.HK)年度纯利大增 每股基本盈利为人民币42.21分
2021年滨州市市属国有企业资产规模破千亿 改革取得明显成效