layui中tips的高级使用及如何正确获取div距离页面顶部的距离
创作场景
公司近期有个需求是点击一个按钮后弹出一个气泡,里面需要根据页面上的条件动态展示一些数据,并且气泡中可以进行搜索及选择需要数据的功能,因为公司使用的是layui框架,所以这里采用layui的tips弹出层解决。
在使用过程中因为气泡中的内容是动态渲染的,且渲染完成后还可以再气泡中选择条件重新请求数据并渲染tip中的内容,所以tip的位置是需要动态变化的,而且ui必须根据设计师的要求来,这就导致tip自带的属性area: 'auto'
不能完全满足需求,还是需要我们根据程序动态判断,这里简单写一个例子说明一下在此场景如果正确使用tips。
tips的简单使用介绍
layer.tips(
// 渲染的dom元素,可以是字符串文本,也可以是dom标签,例如‘<h1>Hello World</h1>’
content,
// 吸附的元素,也就是你需要在哪个元素的周围展示气泡,用jQuery获取即可
// 除了直接传元素外,也可以指定选择器,id或者class等
elem,
// 配置选项,类型为对象,可传入多个属性
options,
);
例如
var buttonDefaultDom = $("#buttonDefault");
layer.tips(
// 展示的内容
'<h1 style="color: black">Hello World</h1>',
// 吸附的元素
buttonDefaultDom,
// 配置
{
tips: [3, '#ffffff'], // 3表示吸附在下方(1234分别对应上右下左),以及后面的tips背景颜色
area: 'auto', // tips宽高,这里设置为自动,也可自己设置为固定值
time: 0, // tips默认3秒后关闭,设置0将不会自动关闭
id: 'buttonDefaultTip' // 唯一标识
}
)
})
展示效果
提示
官网给的介绍比较简单,导致大家可能会认为tips只能传入一些文字提示,其实tips作为弹出层的一员,其中的大部分属性都可以设置,其中的option属性就是为了设置关于大小,弹出时间等设置的,和page层的设置大差不差,只是有一些方法无法作用于tips而已。
高级使用
一、不自动关闭,点击tips外关闭气泡
上面的例子已经使用time: 0
属性设置了tips不会自动关闭,如何实现点击tips外关闭气泡,如下:
// 点击tips外关闭tips
$(window).bind('click', function (event) {
if (!(event.target.id.indexOf("buttonDefault") > -1
|| event.target.id.indexOf("#buttonDefaultTip") > -1
|| $(event.target).parents("#buttonDefaultTip").length > 0)) {
layer.close(buttonDefaultTipIndex)
}
})
这里给window绑定一个点击事件,包含三个判断:
- 当点击的对象id是按钮,也就是上面的默认按钮(id为buttonDefault)则不关闭tips
- 当点击的对象是tips本身(id为buttonDefaultTip)也不会关闭tips
- 当点击的是tips中的子级对象,这里就要找点击对象的父级,有则不关闭(很多人常常忘了这一点)
layer.close(buttonDefaultTipIndex)
是关闭指定下标的弹窗,原理就是layui在每次打开一个弹出层都会赋值一个唯一的id和下标,我们只需要把这个下标存起来,之后根据下标关闭即可。
到这儿别以为就没什么问题了,有个bug是如果连续点击按钮就会无法关闭tips,这回事因为你每次点击就会重新走一次打开tips的方法,但是layui不会渲染生成新的tips,只是会给你返回一个新的index,这就导致你关闭的不是最开始打开的哪个tips。
可以看到确实如此,这里对打开tips和关闭tips的方法进行优化,如下:
var buttonDefaultTipIndex = -1;
var buttonDefaultDom = $("#buttonDefault");
!function () {
buttonDefaultDom.bind('click', function () {
if (buttonDefaultTipIndex < 0 ) {
buttonDefaultTipIndex = layer.tips(
'<h1 style="color: black">Hello World</h1>', buttonDefaultDom, {
tips: [3, '#ffffff'],
area: 'auto',
time: 0,
id: 'buttonDefaultTip'
}
)
}
console.log("buttonDefaultTipIndex:>", buttonDefaultTipIndex)
})
// 点击tips外关闭tips
$(window).bind('click', function (event) {
if (!(event.target.id.indexOf("buttonDefault") > -1
|| event.target.id.indexOf("#buttonDefaultTip") > -1
|| $(event.target).parents("#buttonDefaultTip").length > 0)) {
layer.close(buttonDefaultTipIndex);
buttonDefaultTipIndex = -1;
}
})
}()
在打开tips时判断index值,如果大于0则表示已经打开了,而关闭时将index赋值为-1即可。
设置最小和最大宽度高度
上面说过设计师是规定了tips的样式的,所以这里要设置一下tips宽高的阈值(因为实际tips中的值是根据接口中的数据动态渲染的,所以宽高会动态变化,不设置阈值会超出设计图的样式)。
最大宽高设置:
layui提供了最大宽高的属性,即maxHeight
和maxWidth
,这里要注意:只有在area值为auto时生效,这也是为什么最开始设置area为auto的初衷。
<style>
#buttonDefaultTip {
overflow-y: auto;
}
</style>
buttonDefaultDom.bind('click', function () {
if (buttonDefaultTipIndex < 0 ) {
buttonDefaultTipIndex = layer.tips(
buttonDefaultContent, buttonDefaultDom, {
tips: [3, '#ffffff'],
area: 'auto',
time: 0,
id: 'buttonDefaultTip',
// 最大高度和宽度设置
maxHeight: 200,
maxWidth: 300,
}
)
}
})
效果图
最大高度和宽度就已经实现了,假如现在接口请求没有收到数据,tips得展示一个没有数据的提示,这时候就需要用到最小宽高了(个人认为用最小宽高实现比较好,也可以直接设置无数据提示的样式,但是扩展性相对不好,如果后期需要改为展示一个图片或者其它改动的相对比较大)。
这是没有设置最小宽高的样子。
这是加了最小宽高的样子,看起来顺眼多了。
动态设置tips的位置
为什么要说到动态设置tips的位置,其实layui是自带了这个功能,但是放在特定场景就不适用了,例如:设计师要求点击按钮之后就要弹出气泡,首先在气泡中展示加载数据的loading,待数据加载完成后展示内容,这就导致layui的自动位置定位失效了,因为layui的自动定位一定是你在打开之前就要把渲染的content传给layui,之后它才会自动计算位置,那么上面的需求实际操作肯定是在展示后才给tips中渲染数据(说起来这个设计也是挺烦人的),这就导致了这部分计算需要我们自己实现。
在开始之前大家首先要了解一个知识点,layui的tips位置是基于整个窗口定位的,不像我们之前写的,父元素给relative,子元素给absolute,子元素根据父元素定位,这里的父元素是window窗口,所以实现起来较为麻烦。(提一嘴:layui这里当窗口大小变化后tips时不会跟着移动的,一次性就把位置定位死了,相对elementUI效果不是很好,elementUI是可以根据窗口大小变化,气泡的位置也是会变化的。)
OK,这里需要了解几个知识点:
console.log("window窗口高度:", $(window).height(), "window窗口宽度:",$(window).width())
console.log("默认按钮距离页面的宽高", $("#buttonDefault").offset())
console.log("默认按钮距离父元素的宽高", $("#buttonDefault").position())
console.log("默认按的高度,包含padding", $("#buttonDefault").outerHeight())
// 给tips动态设置top值,left值同理
$("#buttonDefaultTip").parent().css('top', '200px').css('left', '200px')
因为坐的我腰疼,所以这里挑重点和大家说一下,干货干货一定要注意哦:
- offset方法是获取元素距离你页面的高度和宽度,position方法是获取元素距离父元素的宽高,一般是不使用position的,都是基于页面算的。
- 如何知道渲染的tips展示不全面,先获取页面的高度和宽度,在获取tips距离页面的宽高和本身的宽高,用window的宽高减去tips距离window顶部的高度和tips本身进行比较,如果大于tips本身的高度,则表示可以展示全面,小于则不够。
window高度-tips距离页面top
与tips本身高度
比较 - 在知道展示不全面后,可以用tips高度和tips距离页面顶部的top值比较,如果tips高度小则可以定位到按钮的上方,具体top值设置多少就是你的tips距离页面top减去你的按钮高度(这是最标准的top值,但是一般会多减去10-20px,留一点空隙),同样的道理也可以放在右边。
上面的三步骤其实已经满足大多数需求了,但是有一种情况比较恶心,就是我遇到的这种,我的tips是展示在一个弹窗中的,相当于多层弹窗,这时候用offset获取距离页面高度不对劲,为啥,因为你的页面可能已经滚动了,已经有scrollTop值了,一定要注意,减去scrollTop值才是你弹窗中距离页面高度的top值。也就是:
$(“#buttonDefault”).offset() - window.scrollTop()
这个东西很坑,也是我为啥要写这个博客的原因,直接就一整个离谱。
好了,老衲腰疼的受不了了,有些东西没有体现,如果有疑问评论或者私信我。