Vue3 实现双盒子定位Overlay的示例
在Vue3中,使用可以很优雅的把某个组件渲染到根节点之外的节点,同时使其渲染的内容不丧失响应式和对应的生命周期函数调用。那么基于此,用实现相对于某一元素的Overlay。实际上,这篇文章跟Vue3的关系不大,只是通过Vue3讲解一类Overlay的设计方法。
原理
要实现相对于某一元素的Overlay需要依靠两个元素,Origin和Panel,Origin表示相对于的元素,而Panel表示Overlay本身,实现方法主要有两种。
文本流定位法,基于position的absolute和relative特性,将Panel形成相对于Origin的位置来定位的方式。
Overlay基于Origin做固定偏移的双盒子定位法,也就是本文需要讲解的方法。
实现首先,通过,能够建立顶层Overlay,也就是在根节点创建一个新的节点。
setup(_,ctx){
constoriginRef=ref();
constpanelRef=ref();
constpanelStyle=ref({position:'absolute'});
//...
return()=>(
<>
origin
>
);
}
拿到这两者的domref后,需要通过实时计算Origin的盒子的大小和位置,来获得Panel的相对偏移。在Vue中,元素只有在mounted后才能获取得到,所以可以通过composition-api的onMouted来获取具体元素。然后再在生命周期中进行计算。
计算两个盒子的相对位置
如何计算Origin的大小和位置,以及获取其变化后的监听。Origin的大小和位置,通过getBoundingClientRect这一API来获取,这一就可以开始计算Overlay的相对位置。假设我们要把Overlay放在Origin的正下方,计算函数应该是这样的。
constpanelStyle=ref({position:'absolute'});
onMounted(()=>{
constorigin=originRef.value;
constpanel=panelRef.value;
if(!origin||!panel){
return;
}
constcalculate=()=>{
constrect=origin.getBoundingClientRect();
//原点为origin元素的底边中央正下方
constoriginX=rect.left+(rect.width/2);
constoriginY=rect.bottom;
//panel的坐标为到原点的偏移
constpanelRect=panel.getBoundingClientRect();
constpanelX=originX-panelRect.width/2;
constpanelY=originY;
//设置panel数据,触发节点变更
panelStyle.value.left=`${panelX}px`;
panelStyle.value.top=`${panelY}px`;
};
});
当然,你还可以计算各个不同方向的Panel坐标(比如,正左、正上、正下等),排列组合一下,一共有种27不同的情况(每个点依赖于两个变量X和Y;每个变量有三种不同的情况,左、中、右,或者,上、中、下)。
监听盒子的变化
在这里,我们将使用浏览器自带的API来对他们进行监听。通过MutationObserver和ResizeObserver,可以很轻松的监听Origin和Panel的大小和位置变化。
首先是监听Origin的大小和位置变化,这里采用的是MutationObserver,因为导致位置变化的原因只能是style,所以只需要监听style的变化即可。
constorigin$=newMutationObserver(calculate);
origin$.observe(origin,{
//只需要拿到attribute的style的变化即可
attributeFilter:['style'],
});
Panel只需要监听其大小的变化,大小变化有一个更加完美的API,ResizeObserver。
constpanel$=newResizeObserver(calculate);
panel$.observe(panel);
然后,需要在dom销毁前取消监听。
//dom销毁前取消监听
onBeforeUnmount(()=>{
origin$.disconnect();
panel$.disconnect();
});
监听窗口事件
为了能够正确的获取变化,我们需要监听两个事件:resize和scroll.
//为了能够在滚动事件捕获前进行计算,带有滚动条的子元素也会因此触发计算
window.addEventListener('scroll',calculate,true);
window.addEventListener('resize',calculate);
最后,仍然要在销毁前取消事件。
//dom销毁前取消监听
onBeforeUnmount(()=>{
window.removeEventListener('scroll',calculate,true);
window.removeEventListener('resize',calculate);
});
至此,已经完成基本的双盒子定位法的Overlay的设计。
小结
通过双盒子定位来构建的Overlay能够有效规避CSS带来的问题zindex等一系列相关的问题,只用通过计算盒子之间的相对偏移,就能让Panel附着于Origin上,这样,实现类似下拉或者Tooltip等功能的时候,就会非常有用。同时,附上一个简单例子,希望能带来一些启发。
以上就是Vue3实现双盒子定位Overlay的示例的详细内容,更多关于vue3实现Overlay的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。