使用 AbortSignal 移除事件监听器
现在有个需求,弹窗打开时,监听窗口大小变化,并动态调整弹窗大小,避免弹窗比窗口还大,导致弹窗无法操作。弹窗关闭后,移除监听 resize
。因为执行时需要有参数,所以 removeEventListener
并不是很适用。
现在有个需求,弹窗打开时,监听窗口大小变化,并动态调整弹窗大小,避免弹窗比窗口还大,导致弹窗无法操作。弹窗关闭后,移除监听 resize
。因为执行时需要有参数,所以 removeEventListener
并不是很适用。
为了减少表格列的长度,想着把行操作都放到鼠标右键菜单去。可惜Layui的表格目前还不支持右键菜单事件,只能自己去实现了。
layui 的表格头部工具栏左侧图标只有筛选列、导出和打印,功能有点少。经过查阅源代码和手册,找到了全局添加自定义工具的方法,在此记录一下。
查阅手册,配置头部工具栏左侧图标配置,的方式如下:
layui.table.render({ //其它参数在此省略
defaultToolbar: ['filter', 'print', 'exports', {
title: '提示' //标题
,layEvent: 'LAYTABLE_TIPS' //事件名,用于 toolbar 事件中使用
,icon: 'layui-icon-tips' //图标类名
}]
});
字符串的工具是默认自带的,如果是自定义,需要用对象。参照示例,我在这里加一个刷新工具。
layui.table.render({ //其它参数在此省略
defaultToolbar: ['filter', 'print', 'exports', {
title: '刷新'
,layEvent: 'LAYTABLE_REFRESH'
,icon: 'layui-icon-refresh'
}]
});
在layui.table.render()
里定义只适用于单个表格,而我想的是全局默认都有。再经过一番研究,找到设置全局项方法layui.table.set()
,可以在全局公共文件里去设置默认的defaultToolbar
。
layui.use('table', () => {
layui.table.set({
defaultToolbar: [
'filter', 'print', 'exports'
, {title: '刷新', layEvent: 'LAYTABLE_REFRESH', icon: 'layui-icon-refresh'}
]
})
})
工具图标加上去了,接下来就是监听刷新按钮的事件了。Layui的底层API提供了layui.onevent()
方法,用于监听事件。
layui.onevent('table', 'toolbar()', obj => {
// 判断是否是刷新事件(LAYTABLE_REFRESH)
if ("LAYTABLE_REFRESH" === obj.event) {
// 刷新当前表格
layui.table.reload(obj.config.id);
}
})
到此,自定义工具已搞定,以下是完整代码:
layui.use('table', () => {
// 设置默认表格头部工具栏左侧图标
layui.table.set({
defaultToolbar: [
'filter', 'print', 'exports'
, {title: '刷新', layEvent: 'LAYTABLE_REFRESH', icon: 'layui-icon-refresh'}
]
})
// 监听表格头部工具栏事件
layui.onevent('table', 'toolbar()', obj => {
// 判断是否是刷新事件(LAYTABLE_REFRESH)
if ("LAYTABLE_REFRESH" === obj.event) {
// 刷新当前表格
layui.table.reload(obj.config.id);
}
})
})
layui的数据表格用起来的确很方便,开发时能节省很多时间。但是,在投入使用后,导出的表格却是能收到很多反馈,说内容不对。不对的地方主要体现在身份证号码之类的比较长数值,用Excel软件打开后,15位以后的数值会丢失,导致身份证号码不完整。Layui最近一两年的更新力度越来越小了,经常跳票,也不知道能活多久,只能先自己动手吧~
首先,我们用文本查看工具查看导出的内容,可以确定,导出的身份证号码是完整,但用Excel软件打开之后,就出问题了。为此,我百度了下Excel的处理机制,得知,Excel显示数字时,如果数字大于12位,它会自动转化为科学计数法,如果数字大于15位,它不仅用于科学技术法表示,还会只保留高15位,其他位都变0。
如果要解决这个问题,目前只想到一个解决方法,让Excel处理这个数据的时候,不识别它为数值。这要怎么做呢?
首先,我们先前往github下载未压缩过的代码,搜索table.exportFile = function
这个方法的原始代码如下
//表格导出
table.exportFile = function(id, data, type){
var that = this;
data = data || table.clearCacheKey(table.cache[id]);
type = type || 'csv';
var config = thisTable.config[id] || {}
,textType = ({
csv: 'text/csv'
,xls: 'application/vnd.ms-excel'
})[type]
,alink = document.createElement("a");
if(device.ie) return hint.error('IE_NOT_SUPPORT_EXPORTS');
alink.href = 'data:'+ textType +';charset=utf-8,\ufeff'+ encodeURIComponent(function(){
var dataTitle = [], dataMain = [], dataTotal = [];
//表头和表体
layui.each(data, function(i1, item1){
var vals = [];
if(typeof id === 'object'){ //如果 id 参数直接为表头数据
layui.each(id, function(i, item){
i1 == 0 && dataTitle.push(item || '');
});
layui.each(table.clearCacheKey(item1), function(i2, item2){
vals.push('"'+ (item2 || '') +'"');
});
} else {
table.eachCols(id, function(i3, item3){
if(item3.field && item3.type == 'normal' && !item3.hide){
var content = item1[item3.field];
if(content === undefined || content === null) content = '';
i1 == 0 && dataTitle.push(item3.title || '');
vals.push('"'+ parseTempData(item3, content, item1, 'text') + '"');
}
});
}
dataMain.push(vals.join(','));
});
//表合计
layui.each(that.dataTotal, function(key, value){
dataTotal.push(value);
});
return dataTitle.join(',') + '\r\n' + dataMain.join('\r\n') + '\r\n' + dataTotal.join(',');
}());
alink.download = (config.title || 'table_'+ (config.index || '')) + '.' + type;
document.body.appendChild(alink);
alink.click();
document.body.removeChild(alink);
};
然后将里面的
vals.push('"'+ parseTempData(item3, content, item1, 'text') + '"');
替换成
content = parseTempData(item3, content, item1, 'text').replace(/(^\s*)|(\s*$)/g, "");
if (/^\d+$/.test(content) && content.length > 15 && type == 'xls') {
vals.push('="'+ content + '"');
} else {
vals.push('"'+ content + '"');
}
显示问题解决了,但不适合用于数据运算,但办公室的Excel大神们应该有办法吧。反正我能让他正常显示就行了,其它我不管,哈哈。
哦,对了,差点忘了标题。上面只是解决了数值大于15位会丢失尾数的问题,并没有解决科学计数法的问题。如果想不显示科学计数法,将里面的代码替换下即可。其实推荐使用上面的代码就可以了,科学计数法问题可以设置单元格格式来解决。
vals.push('"'+ parseTempData(item3, content, item1, 'text') + '"');
替换成
content = parseTempData(item3, content, item1, 'text').replace(/(^\s*)|(\s*$)/g, "");
if (/^\d+$/.test(content) && content.length > 12 && type == 'xls') {
vals.push('="'+ content + '"');
} else {
vals.push('"'+ content + '"');
}
最近有做一个项目,需要根据用户当前位置自动填写省市区,然后心里有选择:H5原生定位、百度地图、腾讯地图和高德地图。
既然是做公众号,还是比较偏向用腾讯自家的地图--腾讯地图。不是因为它好,主要就是怕用其它的不稳定。
为什么呢?主要怕腾讯那一天搞什么限制,限制使用其它地图,倒是定位功能无法正常使用。
觉得多虑的话,可以想想淘宝抖音为什么在微信打不开。好了,不说这么多废话了,回归正题~
申请网址:https://lbs.qq.com/dev/console/key/manage
调用地图服务需要用到KEY,所以需要申请。申请流程也很简单,不用怎么说了,直接打开上面的网址申请即可。
<script charset="utf-8" src="https://apis.map.qq.com/tools/geolocation/min?key={你的KEY}&referer={你的网站名}"></script>
官方有提供三种用法,几种用法经过测试,第三种相对比较稳定,所以这里写的是第三种用法。
官方文档:https://lbs.qq.com/tool/component-geolocation.html
第一次尝试根据GPS定位,如果失败(用户拒绝了获取精确位置),则尝试根据IP地址定位。
获取成功后,直接根据返回对象里数据拼接即可
let geolocation = new qq.maps.Geolocation();
geolocation.getLocation(
// 获取成功回调
function (position) {
// {"module":"geolocation","type":"cache","adcode":"4402**","nation":"中国","province":"广东省","city":"韶关市","district":"**区","addr":"***","lat":24.***57,"lng":113.***708,"accuracy":3720}
console.log(position);
},
// 获取失败回调
function () {
console.info('获取精确定位失败,尝试通过IP地址获取位置信息');
geolocation.getIpLocation(
// 获取成功回调
function (position) {
// {"module":"geolocation","adcode":440204,"type":"ip","nation":"中国","province":"广东省","city":"韶关市","district":"","addr":"","lat":24.80446,"lng":113.61095,"accuracy":10000}
console.log(position);
},
// 获取失败回调
function () {
console.info('尝试通过IP地址获取位置信息失败');
alert("您的当前位置获取失败,请手动填写安装地区");
}
)
},
{
// 获取定位超时时间,超过这个时间则直接失败,单位:秒
timeout: 30,
failTipFlag: true
}
);