window.open和window.showModalDialog的异同与子父窗口之间值的传递
大家对于window.open都比较了解,window.open确实可以满足我们绝大部分的需求,但当你不可避免的要使用window.showModalDialog时,你可能就对它知之甚少了。
首先来谈谈他们的异同:
1、相同点:这两种方式都可以打开新窗口。
2、前者是非阻塞式,也可以说非模态窗口。而后者是阻塞式模态窗口。阻塞或者模态窗口,只有你把当前窗口关闭后,才能去操作父亲窗口。所以ModalDialog也称为HTML文档的模式对话框。
3、传值方式和参数不同,这个在下文会详细介绍。
说完window.open和window.showModalDialog的异同,下面就该谈谈它们的用法了。
1、window.open(url, name, size);
url:要打开新窗口的地址url;
name:打开新窗口的名称,若名称相同,则之后打开的窗口会覆盖之前的窗口;若不相同,则会再打开一个新窗口;
size:长宽等参数(常用);
例:window.open("sample.do","newWindow","height=200,width=400");
2、
var
retunrnVaule
= window.showModalDialog(url, arguments, size);
url:要打开新窗口的地址url;
arguments:传到子窗口的参数,可以传值,但一般直接写window,代表将整个父窗口都传到子窗口中,那父窗口所有的值都能在子窗口中取到
了;
size:长宽等参数(常用);
var retunrnVaule = window.showModalDialog("modal.do",window,"dialogWidth=200px;dialogHeight=100px");
然后我们再来说说它们父子窗口间的传值是如何完成的吧。
1、
window.open:
父窗口向子窗口传值,window.open的父窗口向子窗口传值可以通过url直接来传递到后台,在后台再将要返回的值塞到子窗口。这就完成了父
窗口向子窗口值的传递。
例:
window.open("sample.do?value='value'","newWindow","height=200,width=400");
还有一种不为人知的方式,因为子窗口可以通过window.parent来获取父窗口,所以可以直接在子窗口调用父窗口的标签来获
取某标签的值,同样可以在子窗口获取父窗口的值。
例:window.parent.$("#input").val();
子窗口向父窗口传值,window.open子窗口向父窗口传值的方式,我一般都会使用用window.parent来调用父窗口方法,将想要传递的值放在参
数中,执行父页面方法的同时,值也传递过去了,这就实现了子窗口向父窗口的传值。
例:window.parent.setValue(value1, value2);
2、
window.showModalDialog:
父窗口向子窗口传值,window.showModalDialog的父窗口向子窗口传值前文已经说过在参数中直接写上window就可以将整个父页面给传到子窗
口了。子窗口可以通过window.dialogArguments获取父窗口所有的方法和标签内容。
例:window.dialogArguments.$("#input").val();
子窗口向父窗口传值,window.showModalDialog的子窗口向父窗口传值有两种,
第一种方式和window.open的传值方式类似,个人比较推荐这种
方法,通过window.dialogArguments来调用父页面方法,并通过方法的参数来传值。
不过这里有一点要提醒大家注意的,
window.dialogArguments有些浏览器不支持(如:360浏览器兼容模式),那么怎么办呢。
通过实验我发现,ie只认识window.dialogArguments
,而其他浏览器有的不认识window.dialogArguments却可以通过window.opener来调用父页面方法,这时候我们可以先判断是否是ie浏览器,把
这个只认识window.dialogArguments的就用window.dialogArguments来调用父页面方法,而其他浏览器都认识window.opener,所以可以使用
window.opener来调用父页面方法。
例:function parentFunc(value1, value2){
var isIE = false;
//这行代码可以判断是否是ie浏览器
if (window.navigator.userAgent.indexOf("Trident") != -1){
isIE= true;
}
//通过是否是ie浏览器来分别进行父页面方法的调用
if(isIE){
window.dialogArguments.func(value1, value2);
}else{
window.opener.func(value1, value2);
}
}
另一种方法比较笨重,不够灵活,但代码量比较少,更加简洁,就是使用window.showModalDialog自身方法所带的returnValue来进行子页面向
父页面的传值。
父页面定义一个变量来接收window.showModalDialog的返回值,子页面通过window.returnValue(固定写法)来将值返回给父
页面,父页面通过定义的变量接收到值后可以继续执行下面的js代码。
例:父页面:var returnValue = window.showModalDialog("child.do",window,"dialogWidth:350px;dialogHeight:350px");
alert(returnValue);
子页面:window.returnValue = “returnValue”;
执行结果:弹出“returnValue”。
这里也可以看出window.open和window.showModalDialog的不同之处,
window.showModalDialog打开新窗口后无法操作父页面,所以js可以停住等到子页面关闭时再继续执行剩下的js,而window.open打开新窗口后
还可以对父页面进行操作,所以也就没办法拥有这个功能了。
这种方法也可以成功的将值从子页面传递到父页面。但本人亲测后发现谷歌浏览器竟然不兼容,瞬间感觉身体被掏空。不过在经历过不断的尝
试之后,机智过人的我还是找到了一个小方法。
我发现谷歌浏览器是认window.opener的,所以我们可以在子页面给父页面的returnValue赋
值,然后再在父页面通过window.returnValue就可以取得子页面传过来的值。
优化后代码为:
父页面:var returnValue = window.showModalDialog("child.do",window,"dialogWidth:350px;dialogHeight:350px");
//for chrome
if (returnValue == undefined) {
returnValue = window.returnValue;
}
alert(returnValue);
子页面:window.returnValue = "returnValue";
//for chrome
if(window.opener){
window.opener.returnValue = "returnValue";
}
这样就可以完美的解决谷歌浏览器不兼容的问题了,是不是很开心呢。
PS:在js中,returnValue == undefined 和 typeof(returnValue) == "undefined" 的效果是一样的。都可以判断变量returnValue是否未定义。
若你还有其他方法解决这个问题,欢迎在下方留下你的方式,大家一起讨论,一起进步,做一只有梦想的网虫!