咋说呢,因为对 layui 不太熟悉,这个弹出框搞了好久,看了好多解决方案,大致尝试了一下其中几种,在坑中无法自拔。。。总之终于搞出来了,在这里分享一下我的笔记。
着急的直接 戳这里 看解决代码。
尝试
1、直接在子页面写弹框代码及弹框定位样式
一开始我就直接在 子页面 上写的弹框代码和样式,然后想定位到父页面上。因为position:absolute
定位要找它最近的父级定位元素,如果没有写,就会找到 html
,而 iframe
子页面就是一个新的 html
文档,所以没办法定位到父页面上。
子页面
<style>
/* 弹框 */
#diolog{position:absolute;top:0;left:0;right:0;bottom:0;z-index:200;margin:0 auto;background:rgba(0,0,0,.5);
}
#diolog .layui-form{width:660px;background:#fff;margin:0 auto;}
</style><body>... <!-- 表格 --><div class="content mt20 bg pd20"><button class="layui-btn layui-btn-sm addBtn">新增</button><table class="layui-table" lay-filter="table" id="table"></table></div><!-- 弹出框 id="diolog"生成弹框时会被替换掉--><div id="diolog"> <div class="layui-form" lay-filter="formDiolog" id="formDiolog"><div class="layui-form-item"><div class="layui-inline"><label class="layui-form-label">行业标识</label><div class="layui-input-inline"><input type="text" name="industryId" autocomplete="off" class="layui-input disabledDom" ></div></div><div class="layui-inline"><label class="layui-form-label">行业名称</label><div class="layui-input-inline"><input type="text" name="industryName" autocomplete="off" class="layui-input"></div></div></div><!--- 。。。。。。 ---></div>
</body>
2、父页面放空div,覆盖整个父页面
看到帖子说子父页面放一个弹框空div
,尝试之后发现:这个遮罩会覆盖整个页面,但是也把弹框中的内容遮挡住了,子页面 z-index
设置 99999 也不管用。目前我还没找到解决办法,有解决的希望能告诉我一下,嘿嘿。
父页面
<style>
#diolog{display:none;position:absolute;top:0;left:0;right:0;bottom:0;z-index:200;margin:0 auto;background:rgba(0,0,0,.5);
}
</style>
<body><!-- 头部 --><header class="boxSizing">...</header><!-- 导航 --><div class="margin clear"><!-- 侧导航 --><ul class="layui-nav layui-nav-tree" lay-filter="layui-nav"></ul> <!-- 子页面 --><iframe frameborder=0 scrolling="no" width="980" id="iframe-box" src="/html/views/industry/index.html"></iframe></div><!-- 弹框 --><div id="diolog"></div>
</body><script>function diologOpen(){$("#diolog").show();}
</script>
子页面,点击新增按钮的时候出现弹框:
$("#addBtn").on("click",function(){$("#formDiolog").show();parent.diologOpen();
})
3、使用 $.load()
加载弹框内容
经过上面的试验之后,就想把子页面写的 DOM 加载到父级上,于是想到了 jQuery 中的 $.load()
方法。
子页面
<!-- 弹出框 id="diolog"生成弹框时会被替换掉-->
<div id="diolog"> <div class="layui-form" lay-filter="formDiolog" id="formDiolog">...<div class="layui-form-item"><div class="layui-input-block"><button class="layui-btn" lay-submit lay-filter="formDemo">立即提交</button><button class="layui-btn layui-btn-primary diologCloseBtn">取消</button></div></div></div>
</div><script>
//新增,调用父页面封装好的打开弹框的方法$(".addBtn").on("click", function(){//第一个参数:在父页面引用当前页面时的路径,第二个参数:新增为false,//第三个是回调函数,返回表单中输入框的字段和值。parent.loadDiolog("../views/industry/index.html", null, function(params){console.log(params); $.ajax({type: "POST",data: params})})})//监听工具条,表格中的弹框table.on('tool(table)', function(obj){var data = JSON.parse( JSON.stringify(obj.data) );if(obj.event === 'edit'){ //编辑 //把点击的哪一行的数据传给父级中的方法parent.loadDiolog("../views/industry/index.html", data, function(params){console.log(params)})}})
</script>
父页面
<style>#diolog{display:none;position:absolute;top:0;left:0;right:0;bottom:0;z-index:200;margin:0 auto;background:rgba(0,0,0,.5);}#diolog #formDiolog{background:#ff9;width: 660px;margin:200px auto;}
</style><body>...<!-- 弹框 --><div id="diolog"></div>
</body><script>
//封装打开弹框的方法,第一个参数:在父页面引入需要弹框的页面的路径
//第二个参数:新增为false,修改时传表格中的数据,第三个是回调函数,返回表单中输入框的字段和值。function loadDiolog(src,data,callback){$("#diolog").show(); //显示遮罩$("#diolog").load(src+" #formDiolog",function(){if( data ){ // 当data为 true 时,说明是修改弹框,给弹框中的表单赋值 layui.use('form',function(){var form = layui.form;$("#diolog").find(":input:not(button)").each(function(item){var name = $(this).attr("name");$(this).val(data[name]);});//点击提交按钮,把表单的数据传给子级form.on("submit(formDemo)",function(data){callback(data);}) }); }}); }//点击取消按钮,隐藏整个遮罩层,需要委托给父元素$("#diolog").on("click",".diologClose",function(){$("#diolog").hide() })
</script>
效果确实出来了,但是违背了我一开始不想写每个页面路径的想法,除此之外,使用 load
加载 DOM
,在性能方面不如 iframe
加载。
- 关于iframe与$.load()哪个更好
- iframe可以直接加载页面,但是要付出降低搜索引擎搜索效率的代价,它引入静态文件的方式是完全独立的,简单意思就是,在页面一(父级页面)用iframe加载了页面二(子级页面),页面二的静态文件不用在页面一上加载,降低了每个页面的加载负荷,增加了每个页面的加载效率;
- 而**$.load()是与它父级页面互相联动的**,如果你想要load某个页面,那么你就要在它的父级页面中引入子级页面的css和js包来控制子页面的样式和效果,这样会增加父级页面的加载负荷,使得父级网页加载变慢,整体影响用户体验性。
解决
关于子页面写弹框覆盖父页面,看到很多都是使用 layui 中的弹框,但是基本上都是再引入 iframe 层,对于这种表格和弹框较多的后面管理项目,因为要引入每个表单文件的路径,不太实用。
于是去看了一下官网。最终还是打算用 layui.layer 去写。。。
在子页面写弹框内容:
<body><!-- 查询条件 -->...<!--- 新增修改弹框 ---><div id="diolog"> <div class="layui-form" lay-filter="formDiolog" id="formDiolog"><div class="layui-form-item"><div class="layui-inline"><label class="layui-form-label">行业标识</label><div class="layui-input-inline"><!-- 给修改弹框需要禁用的输入框添加class名:disabledDom --><input type="text" name="industryId" autocomplete="off" class="layui-input disabledDom" ></div></div><div class="layui-inline"><label class="layui-form-label">行业名称</label><div class="layui-input-inline"><input type="text" name="industryName" autocomplete="off" class="layui-input"></div></div></div><!--- 其他。。。。 ---></div></body><script>$(".addBtn").on("click", function(){ //点击新增按钮,出现弹框diologOpen({ title: "新增行业信息" }, function (data) { //调用打开弹框的方法console.log(data); //data 为弹出框表单中的字段和值,在这里调用新增的接口$.ajax({type: "POST",data: data//....})})});//监听工具条table.on('tool(table)', function(obj){var data = JSON.parse( JSON.stringify(obj.data) ); //赋值时注意深浅拷贝if(obj.event === 'edit'){ //编辑 //点击编辑按钮时,需要给弹框传的值var formData = {title: "编辑行业信息" ,formData: data}diologOpen(formData, function (data) { //调用打开弹框的方法console.log(data); //data 为弹出框表单中的字段和值,在这里调用新增的接口})});// 封装弹出框,给表单赋值.
//formData是传给弹框的值,是一个对象,callback回调函数,是点击弹框中的确认要做的操作。
function diologOpen(data, callback) { layui.use(['layer','form'], function(){var form = layui.form;var index = parent.layer.open({type: 1, //0信息框,默认;1页面层;2iframe层;3加载层;4tips层title: formData.title,content: $("#diolog").html(), //注意后面的.html()btn: ['确认', '取消'],success: function(layero){ //打开弹框的回调// 携带两个参数,分别是layero当前层DOM,index当前层索引if( data.formData ){ //有数据时为修改弹框,修改弹框的表单赋值layero.find(':input').each(function(){ //给表单的输入框赋值,注意 input 前面的:不能省$(this).val( data.formData[$(this).attr("name")] );});layero.find("input.disabledDom").addClass("noDrap"); //修改操作通常标识是不能改的layero.find("input.disabledDom").attr("disabled","disabled"); //禁用输入框form.render();} },yes: function (index, layero) { //点击确认按钮后,把输入框的数据导出到回调函数中。//两个参数index当前层索引、layero当前层DOM对象var data = {}layero.find(':input').each(function(){data[$(this).attr("name")] = $(this).val();})callback(data); parent.layer.close(index); //关闭弹框}});})
}
</script>
父页面:
<style>.noDrap{cursor: no-drop;}/*禁用*/#formDiolog input{height:30px;line-height: 30px;}#formDiolog div label.layui-form-label{text-align: left;padding-right:0;padding-top:0;padding-bottom:0; line-height: 30px;}#formDiolog .layui-btn, .layui-edge, .layui-inline, img{vertical-align: top;}
</style><body></body><!-- 为防止出错,父页面添加依赖 -->
<script>layui.use("layer",function(){var layer = layui.layer;})
</script>
注意:
- 因为弹框加到父级上了,所以弹框中的样式要写在父级的样式文件中。
- 表单赋值/取值有个
form.val()
方法,这里使用会没有效果,原因也是因为 弹框中内容被加到父级上了,而表单赋值是写在子页面上的,所以在子页面做表单赋值操作时要手动去写赋值操作。