说实话,我一看到这个returnValue就有点反感,感觉这个就是IE式的老套的用法,因为项目中有用到就了解了下,以下主要是一些我的理解和发现吧。

PS:returnValuewindow的属性,showModalDialogopenwindow的方法。

returnValue是与showModalDialog搭配使用的,showModalDialog用于打开窗口,与open类似效果,但通过showModalDialog打开窗口时有如下特点:

  1. 打开窗口后,将不能再操作父窗口了(正常情况下,父窗口将获取不到焦点了);
  2. 确切的说父窗口在执行showModalDialog这一步时停止了,等待子窗口操作返回,而showModalDialog之后的js代码也就暂时不会执行了;
  3. returnValue就是返回值,子窗口通过window.returnValue将操作结果返回给父窗口,在子窗口调用window.close方法后,returnValue将作为showModalDialog的返回值传递到父窗口中,之后继续执行showModalDialog后面的js代码;

网上的搜罗了下,都说IE、Firefox支持的,而Chrome虽然有showModalDialog方法,但效果仅仅类似open,且不支持returnValue,至于Opera则完全不支持(应该说的不是Webkit内核的Opera)。

初步写代码测试了下(只测IE、Firefox、Chrome),我写了三个页面,主要逻辑是:t1中打开t2、t2中打开t3、同时每个页面上添加点击测试、刷新测试按钮(用于Chrome测试),基本html代码如下,可直接点击页面地址进行浏览:

t1.html代码:
<!doctype html>
<html>
<meta charset="utf-8"/>
<title>t1</title>
<script>
alert("load t1");
function openT2(){
alert(showModalDialog('t2.html',{msg:"arguments from t1.html",win:window},''));
alert('子窗口已关闭');
}
function openT1Self(){
alert(showModalDialog('t1.html',{msg:"arguments from t1.html",win:window},''));
alert('子窗口已关闭');
}
function closeSelf(){
window.returnValue='从t1正常返回的returnValue';
window.close();
}
if(window.dialogArguments){
if(window.dialogArguments.msg){
alert(window.dialogArguments.msg);
}else{
alert(window.dialogArguments);
}
}
function reloadPage(){
alert('before');
window.location.reload();
alert('after');
}
function setReturnValue(){
var str = prompt("请输入returnValue值")
window.returnValue = "t1在刷新前所赋的returnValue:"+str;
alert("赋值完毕,请点击刷新!");
}
</script>
<body>
<a href="javascript:openT2();">打开t2</a>
<a href="javascript:openT1Self();">打开t1自己</a>
<a href="javascript:closeSelf();">关闭</a>
<a href="javascript:alert('点击了');">Chrome下点击测试</a>
<a href="javascript:setReturnValue();">在刷新前给returnValue赋值</a>
<a href="javascript:reloadPage();">点击刷新</a>
</body>
</html>
t2.html代码:
<!doctype html>
<html>
<meta charset="utf-8"/>
<title>t2</title>
<script>
alert("load t2");
function openT3(){
alert(showModalDialog('t3.html',{msg:"arguments from t2.html",win:window},''));
alert('子窗口已关闭');
}
function closeSelf(){
window.returnValue='从t2正常返回的returnValue';
window.close();
}
if(window.dialogArguments){
if(window.dialogArguments.msg){
alert(window.dialogArguments.msg);
}else{
alert(window.dialogArguments);
}
}
function reloadPage(){
alert('before');
window.location.reload();
alert('after');
}
function setReturnValue(){
var str = prompt("请输入returnValue值")
window.returnValue = "t2在刷新前所赋的returnValue:"+str;
alert("赋值完毕,请点击刷新!");
}
</script>
<body>
<a href="javascript:openT3();">打开t3</a>
<a href="javascript:closeSelf();">关闭</a>
<a href="javascript:alert('点击了');">Chrome下点击测试</a>
<a href="javascript:setReturnValue();">在刷新前给returnValue赋值</a>
<a href="javascript:reloadPage();">点击刷新</a>
</body>
</html>
t3.html代码:
<!doctype html>
<html>
<meta charset="utf-8"/>
<title>t3</title>
<script>
alert("load t3");
function closeSelf(){
window.returnValue='从t3正常返回的returnValue';
window.close();
}
if(window.dialogArguments){
if(window.dialogArguments.msg){
alert(window.dialogArguments.msg);
}else{
alert(window.dialogArguments);
}
}
function reloadPage(){
alert('before');
window.location.reload();
alert('after');
}
function setReturnValue(){
var str = prompt("请输入returnValue值")
window.returnValue = "t3在刷新前所赋的returnValue:"+str;
alert("赋值完毕,请点击刷新!");
}
</script>
<body>
<a href="javascript:closeSelf();">关闭</a>
<a href="javascript:setReturnValue();">在刷新前给returnValue赋值</a>
<a href="javascript:reloadPage();">点击刷新</a>
</body>
</html>
测试1

直接将t1.html文件拖入浏览器浏览进行测试。

测试结果:
  • IE、Firefox没有问题;
  • Chrome下则returnValue几乎无效,具体细节:

    1. showModalDialog效果接近open,即只是打开了一个新窗口而已,父窗口仍然可以操作,而showModalDialog后的语句没有执行,但控制台上却有些信息提示,有一个警告(灰色)和错误(红色):

      Chromium is considering deprecating showModalDialog. Please use window.open and postMessage instead.

      Uncaught SecurityError: Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match.

      警告信息表明Chromium将弃用showModalDialog(经验证,在Chromium38.0.2074.0中,showModalDialog已报undefined错误,看来已被遗弃,见官方Issue345831,不知Chrome之后会不会如此……)。

      错误信息是在关闭子窗口后出来的,这个就是说明了为什么returnValue无效以及showModalDialog后面的语句为什么没执行(报错了么,呵呵),这个错误似乎跟跨域访问有点类似啊。

      PS:在较老版本的Chrome中并不会有这里的警告及错误信息,故可能让人误以为不支持returnValue

      PPS@2014/09/14: 最近无意间在Firefox(版本号是32)的控制台也看到类似的提示信息,如下所示,看来ShowModalDialog的结局可想而知了。

      window.showModalDialog() 已废弃。请使用 window.open() 代替。更多信息见 https://developer.mozilla.org/en-US/docs/Web/API/Window.open

    2. 当t1.html通过showModalDialog打开t1.html(即自己)的时候,returnValue竟起作用了,但在子窗口打开的情况下父窗口仍然可以操作,不同的是的showModalDialog后面的语句在关闭子窗口后执行了,说明此时没有1中的那个错误了;

    3. 但如果子页面刷新了,则无论之后给returnValue赋什么值,最终showModalDialog的返回值将一直是子页面第一次刷新前给returnValue所赋的值,如果第一次刷新前没有给returnValue赋值,则将是undefined,这说明子页面在刷新后与父页面失去了联系,导致returnValue失效;

    4. 在子窗口打开情况下,虽然父窗口能够操作,但在父窗口中点击“点击刷新”后两个alert都执行了,而页面却没有刷新,说明有些特殊操作如window.location.reload();将会等到子窗口关闭后才会执行。

通过测试1得知在chrome下本地直接浏览网页的形式使用showModalDialog存在类似跨域访问的错误,因此需要将网页放到Web应用服务器上测试,至于子页面刷新导致的问题也许就那样了,算是个bug吧。

测试2

将三个页面放到Web应用服务器(Tomcat)上,然后打开t1.html浏览进行测试。

测试结果:
  • IE、Firefox没有问题;
  • Chrome下则returnValue基本有效,具体细节:
    1. 正常操作情况下,能够通过returnValue返回数据,showModalDialog后面的代码也能在关闭子窗口后执行;
    2. 但如果子页面刷新了,则无论之后给returnValue赋什么值,最终showModalDialog的返回值将一直是子页面第一次刷新前给returnValue所赋的值,如果第一次刷新前没有给returnValue赋值,则将是undefined,这说明子页面在刷新后与父页面失去了联系,导致returnValue失效;
    3. 在子窗口打开情况下,虽然父窗口能够操作,但在父窗口中点击“点击刷新”后两个alert都执行了,而页面却没有刷新,说明有些特殊操作如window.location.reload();将会等到子窗口关闭后才会执行。

总结

鉴于网上发表的关于Chrome之returnValue的文章都是几年前的,也许那时确实是完全不支持returnValue吧,不过我拿了个较老的版本(v11)测过,结果大致跟新版一样。

但Chrome虽然支持returnValue,但使用体验却不怎么样,有以下几点:

  1. 打开子窗口情况下,还是能够操作父窗口;
  2. 子窗口在刷新后,returnValue就失效了(window.dialogArguments也变为undefined了),只能返回第一次刷新前的returnValue(该问题可通window.opener传参解决,该属性指向父窗口,且不会因为刷新导致失效,具体请参考ref1文中的“解决returnValue问题”小节)

于是乎可以说Chrome不支持returnValue吧,在之后的版本中showModalDialog这个方法应该会被移除了,所以说这个没有什么意义了啊。

如果一定要继续用showModalDialog的话,可以考虑在子窗口中通过window.opener与父窗口进行传参来代替returnValue的方式,而用open来代替showModalDialog,而在子窗口打开情况下,可以在父窗口中覆盖一层div来禁用用户操作等等,还是可以将就着模拟showModalDialog的效果的,但要完全模拟,有点困难啊。

参考资料

returnValue of Chrome的更多相关文章

  1. chrome中showModalDialog解决方案

    调用myShowModalDialog function myShowModalDialog(url, width, height, callback) { if(window.showModalDi ...

  2. onbeforeunload事件兼容性操作

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  3. Chrome不支持showModalDialog模态对话框和无法返回returnValue的问题

    父窗体部分js代码: var returnValue = window.showModalDialog("son.html ", window); //for chrome if ...

  4. 【转载】showModalDialog returnValue is undefined in Google Chrome

    showModalDialog returnValue is undefined in Google Chrome Posted on August 22, 2012by briancaos For ...

  5. JavaScript自定义浏览器滚动条兼容IE、 火狐和chrome

    今天为大家分享一下我自己制作的浏览器滚动条,我们知道用css来自定义滚动条也是挺好的方式,css虽然能够改变chrome浏览器的滚动条样式可以自定义,css也能够改变IE浏览器滚动条的颜色.但是css ...

  6. [No000080]右键解锁增强Chrome插件开发,破除防复制

    昨天用360极速(虽然我不喜欢360.)浏览器,登陆知乎查阅一些东西,突然感觉有些观点很赞同,想copy转载一下,我了个去,它丫的居然不让我复制. 地址:https://www.zhihu.com/q ...

  7. Javascript操作剪切板数据(支持IE、Chrome、360、搜狗),亲测!

    clipboarddata只能在IE浏览器中使用,在chrome下会提示对象未定义!以下的方法支持IE.Chrome.360.搜狗等浏览器,其它浏览器还未验证. <!DOCTYPE html&g ...

  8. js添加事件、移除事件、阻止冒泡、阻止浏览器默认行为等写法(兼容IE/FF/CHROME)

    转自:http://blog.csdn.net/itchiang/article/details/7769341 添加事件   var addEvent = function( obj, type, ...

  9. 从Chrome源码看JS Array的实现

    .aligncenter { clear: both; display: block; margin-left: auto; margin-right: auto } .crayon-line spa ...

随机推荐

  1. Android学习笔记-tween动画之xml实现

    继上篇tween动画的java实现:http://www.cnblogs.com/fengtengfei/p/3957800.html, 这里我接着介绍一下tween动画的xml实现的方法,   首先 ...

  2. Runtime ----- 带你上道

    在IOS开发和学习过程中,我们经常会接触到一个词: Runtime  .很多开发者对之既熟悉又陌生,基本都是浅尝辄止,达不到灵活使用的水平(话说开发中也确实不经常用..)本文和大家一起研究一下,Run ...

  3. Git分支管理策略(转)

    作者: 阮一峰 日期: 2012年7月 5日 使用"版本管理系统"(Version Control System). 眼下最流行的"版本管理系统",非Git莫属 ...

  4. vue学习笔记(1)

    1.检测变化 <ul> <li v-for="item in list">{{item}}</li> </ul> <scrip ...

  5. bzoj 1645: [Usaco2007 Open]City Horizon 城市地平线【线段树+hash】

    bzoj题面什么鬼啊-- 题目大意:有一个初始值均为0的数列,n次操作,每次将数列(ai,bi-1)这个区间中的数与ci取max,问n次后元素和 离散化,然后建立线段树,每次修改在区间上打max标记即 ...

  6. 17年day2

    /* 嗯,明天就出发了. 嗯,终于快要结束了. 考试日常挂T1 今天晚上老师们请我们吃水饺,还有一个大蛋糕. 虽然没怎么吃蛋糕23333 还好我的水饺是白菜馅的~~~ 晚上学哥学姐们发视频送祝福,谢谢 ...

  7. sqlalchemy配置多读写库多连接后的关系设置

    前言 一般来说,解决sqlalchemy 连接多个库的最简单的方式是新建两个或多个db.session 相互没有关联,modle配置不同的db.session来连接,这样的话,relationship ...

  8. 构造+暴力 Codeforces Round #283 (Div. 2) B. Secret Combination

    题目传送门 /* 构造+暴力:按照题目意思,只要10次加1就变回原来的数字,暴力枚举所有数字,string大法好! */ /************************************** ...

  9. 转 linux shell自定义函数(定义、返回值、变量作用域)介绍

    linux shell 可以用户定义函数,然后在shell脚本中可以随便调用.下面说说它的定义方法,以及调用需要注意那些事项. 一.定义shell函数(define function) 语法: [ f ...

  10. web项目无法部署到eclipse配置的本地tomcat

    一.发现问题 在eclipse中新建Dynamic Web Project,配置好本地的tomcat并写好代码后选择Run on Server,但运行后发现在tomcat的安装目录下的webapps并 ...