咋说呢,因为对 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()
方法,这里使用会没有效果,原因也是因为 弹框中内容被加到父级上了,而表单赋值是写在子页面上的,所以在子页面做表单赋值操作时要手动去写赋值操作。