背景
最近使用了layui的前端框架,也在慢慢适应中,好多功能都已经封装得很实用,遇到不会的功能,看看官网的demo的文档,都还是可以解决的,毕竟咱们的模仿能力还是可以的。
记录一下昨天遇到的一个问题,就是我想在表格的头部工具栏,增加一个文件上传的接口,用于数据的批量导入,就简单的写了一个按钮,使用upload组件实现了功能,但是奇怪的事情发生了,第一次上传成功之后,页面不刷新,再次点击第二次的话,是无法上传文件,向后台发出请求的,最后排查的原因是,按钮上面的事件没有被渲染,导致上传组件无法与指定的按钮进行绑定。
问题重现
- 在工具栏声明按钮,控件ID为import
<script type="text/html" id="headToolbarTpl">
<input type="button" class="layui-btn layui-btn-sm" id="import" value="导入明细"/>
<input type="button" class="layui-btn layui-btn-sm" lay-event="download" style="margin-left: 10px" value="下载模板"/>
</script>
- 调用upload组件,绑定控件按钮
//指定允许上传的文件类型
upload.render({
elem: '#import'
, url: BASE_WEB + 'enterprisepoints/enterprisePointsBatch/importExcel' //改成您自己的上传接口
, accept: 'file' //普通文件
, acceptMime: '.xls,.xlsx'
, done: function (res) {
if (res.code == 400) {
table.reload(tableId);
layer.msg(res.msg, {time: 4000});
else {
table.reload(tableId);
bindTableToolbarFunction();
bnyKit.errorMsg(res.msg);
}
// Layui的table在reload之后使用ID绑定的按钮失效,需要重新绑定
bindTableToolbarFunction();
}
});
问题解决
方案一(原始方案,不推荐)
问题是在进行操作后,没有执行渲染事件,那么好,我在执行的每次动作之后,都重新执行一下渲染就可以。
- 将渲染方法封装为一个函数
// Layui的table在reload之后使用ID绑定的按钮失效,需要重新绑定
function bindTableToolbarFunction() {
// 绑定新增用户事件
upload.render({
elem: '#import'
, url: BASE_WEB + 'enterprisepoints/enterprisePointsBatch/importExcel' //改成您自己的上传接口
, accept: 'file' //普通文件
, acceptMime: '.xls,.xlsx'
, done: function (res) {
if (res.code == 400) {
table.reload(tableId);
layer.msg(res.msg, {time: 4000});
} else {
table.reload(tableId);
layer.msg('上传成功');
layer.msg(res.data, {
time: 5000, //20s后自动关闭
btn: ['关闭']
});
}
}
});
}
- 在每个动作之后,都需要执行该函数,例如
if (layEvent === 'details') {
layer.open({
type: 2
, title: '明细详情'
, content: BASE_WEB + 'enterprisepoints/enterprisePointsBatch/details?batchId=' + data.id
, maxmin: true
, area: area // 宽高
, btn: ['关闭']
, yes: function (index, layero) {
layer.closeAll();
}
});
bindTableToolbarFunction();
}
- 我一开始使用了该方式,但是在测试之后发现,有的情况还是不可以,而且如果我在页面添加其他操作的话,都需要是执行渲染函数,虽然已经被封装为函数了,但是还是新操作还是会被污染。
方案二(推荐使用)
我们可以沿用layui提供了头部工具栏的功能,只是我需要去避免绑定按钮的失效渲染即可,
表格的工具栏模板如上,我猜想,每次在进行工具栏渲染的时候,一定是按照toolbarDemo这个id进行的,我的控件id,正式因为渲染才失效的,那么我是不是可以把按钮拿出来,然后进行上传组件的绑定呢,除此之外,lay-event这个控件还是正常使用,只是在lay-event事件处理的时候,再出发我的上传按钮的点击动作。
- 第一步,将按钮拿到模板外面
<!--头部工具栏模板-->
<button type="button" class="layui-btn layui-btn-sm" id="importFile" value="导入明细" style="display: none"/>
<script type="text/html" id="headToolbarTpl">
<input type="button" class="layui-btn layui-btn-sm" lay-event="import" style="margin-left: 10px" value="导入明细"/>
<input type="button" class="layui-btn layui-btn-sm" lay-event="download" style="margin-left: 10px"
value="下载模板"/>
</script>
注:由于我在模板中已经加了导入明细的按钮操作,所以我将自己声明的按钮隐藏掉,防止页面重复出现
- 第二步:绑定生成的按钮事件,即绑定upload组件
//指定允许上传的文件类型
upload.render({
elem: '#importFile'
, url: BASE_WEB + 'enterprisepoints/enterprisePointsBatch/importExcel' //改成您自己的上传接口
, accept: 'file' //普通文件
, acceptMime: '.xls,.xlsx'
, done: function (res) {
if (res.code == 400) {
table.reload(tableId);
layer.msg(res.msg, {time: 4000});
} else if (res.code == 200) {
table.reload(tableId);
//bindTableToolbarFunction();
bnyKit.sucessMsg(res.msg)
} else {
table.reload(tableId);
//bindTableToolbarFunction();
bnyKit.errorMsg(res.msg);
}
// Layui的table在reload之后使用ID绑定的按钮失效,需要重新绑定
//bindTableToolbarFunction();
}
});
- 第三步,将event的时间处理,转到隐藏按钮的点击动作
case 'import':
$("#importFile").click();
break;
总结
网上确实有好多人遇到这个问题,但是试了好多个方案,都不是很理想,其中还有使用table.render中的done函数的,但是也还是不行,遂自己总结一下,避免后面踩坑。