说实话,我一看到这个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代码:
  1. <!doctype html>
  2. <html>
  3. <meta charset="utf-8"/>
  4. <title>t1</title>
  5. <script>
  6. alert("load t1");
  7. function openT2(){
  8. alert(showModalDialog('t2.html',{msg:"arguments from t1.html",win:window},''));
  9. alert('子窗口已关闭');
  10. }
  11. function openT1Self(){
  12. alert(showModalDialog('t1.html',{msg:"arguments from t1.html",win:window},''));
  13. alert('子窗口已关闭');
  14. }
  15. function closeSelf(){
  16. window.returnValue='从t1正常返回的returnValue';
  17. window.close();
  18. }
  19. if(window.dialogArguments){
  20. if(window.dialogArguments.msg){
  21. alert(window.dialogArguments.msg);
  22. }else{
  23. alert(window.dialogArguments);
  24. }
  25. }
  26. function reloadPage(){
  27. alert('before');
  28. window.location.reload();
  29. alert('after');
  30. }
  31. function setReturnValue(){
  32. var str = prompt("请输入returnValue值")
  33. window.returnValue = "t1在刷新前所赋的returnValue:"+str;
  34. alert("赋值完毕,请点击刷新!");
  35. }
  36. </script>
  37. <body>
  38. <a href="javascript:openT2();">打开t2</a>
  39. <a href="javascript:openT1Self();">打开t1自己</a>
  40. <a href="javascript:closeSelf();">关闭</a>
  41. <a href="javascript:alert('点击了');">Chrome下点击测试</a>
  42. <a href="javascript:setReturnValue();">在刷新前给returnValue赋值</a>
  43. <a href="javascript:reloadPage();">点击刷新</a>
  44. </body>
  45. </html>
t2.html代码:
  1. <!doctype html>
  2. <html>
  3. <meta charset="utf-8"/>
  4. <title>t2</title>
  5. <script>
  6. alert("load t2");
  7. function openT3(){
  8. alert(showModalDialog('t3.html',{msg:"arguments from t2.html",win:window},''));
  9. alert('子窗口已关闭');
  10. }
  11. function closeSelf(){
  12. window.returnValue='从t2正常返回的returnValue';
  13. window.close();
  14. }
  15. if(window.dialogArguments){
  16. if(window.dialogArguments.msg){
  17. alert(window.dialogArguments.msg);
  18. }else{
  19. alert(window.dialogArguments);
  20. }
  21. }
  22. function reloadPage(){
  23. alert('before');
  24. window.location.reload();
  25. alert('after');
  26. }
  27. function setReturnValue(){
  28. var str = prompt("请输入returnValue值")
  29. window.returnValue = "t2在刷新前所赋的returnValue:"+str;
  30. alert("赋值完毕,请点击刷新!");
  31. }
  32. </script>
  33. <body>
  34. <a href="javascript:openT3();">打开t3</a>
  35. <a href="javascript:closeSelf();">关闭</a>
  36. <a href="javascript:alert('点击了');">Chrome下点击测试</a>
  37. <a href="javascript:setReturnValue();">在刷新前给returnValue赋值</a>
  38. <a href="javascript:reloadPage();">点击刷新</a>
  39. </body>
  40. </html>
t3.html代码:
  1. <!doctype html>
  2. <html>
  3. <meta charset="utf-8"/>
  4. <title>t3</title>
  5. <script>
  6. alert("load t3");
  7. function closeSelf(){
  8. window.returnValue='从t3正常返回的returnValue';
  9. window.close();
  10. }
  11. if(window.dialogArguments){
  12. if(window.dialogArguments.msg){
  13. alert(window.dialogArguments.msg);
  14. }else{
  15. alert(window.dialogArguments);
  16. }
  17. }
  18. function reloadPage(){
  19. alert('before');
  20. window.location.reload();
  21. alert('after');
  22. }
  23. function setReturnValue(){
  24. var str = prompt("请输入returnValue值")
  25. window.returnValue = "t3在刷新前所赋的returnValue:"+str;
  26. alert("赋值完毕,请点击刷新!");
  27. }
  28. </script>
  29. <body>
  30. <a href="javascript:closeSelf();">关闭</a>
  31. <a href="javascript:setReturnValue();">在刷新前给returnValue赋值</a>
  32. <a href="javascript:reloadPage();">点击刷新</a>
  33. </body>
  34. </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. 三星手机root后开启调试模式

    背景说明:三星手机高版本的手机进行root后也无法安装xposed,无法开启debuggable,使用androistdio无法进行调试. 1 .连接ddms无法显示正在运行的进程. 2.安装mpro ...

  2. 【Silverlight】Bing Maps学习系列(四):使用图钉层(Pushpin layer)及地图图层(MapLayer)(转)

    [Silverlight]Bing Maps学习系列(四):使用图钉层(Pushpin layer)及地图图层(MapLayer) 如果我们需要在Bing Maps中加入一个小图钉标记,该如何实现了? ...

  3. mysql与mongoDB的特点和优劣

    首先分析下mysql与mongoDB的特点和优劣 从图中分析: 再来分析下应用场景: a.如果需要将mongodb作为后端db来代替mysql使用,即这里mysql与mongodb 属于平行级别,那么 ...

  4. IDEA中项目src目录下无法创建java文件的问题

    出现的问题如下,是因为该目录不是源码目录 解决办法 设置成功

  5. Tomcat优化和JVM分析工具

    Tomcat的常见优化和JVM常见分析工具 Tomcat的常用优化配置 (1) 内存空间: /etc/sysconfig/tomcat JAVA_OPTS="-server -Xms32g ...

  6. 洛谷 P2365 任务安排【dp】

    其实是可以斜率优化的但是没啥必要 设st为花费时间的前缀和,sf为Fi的前缀和,f[i]为分组到i的最小花费 然后枚举j转移,考虑每次转移都是把j到i分为一组这样意味着j及之后的都要增加s的时间,同时 ...

  7. Net 发布网站中遇到的几点问题

    1.windows 身份验证设置 打开IIS==>=>找到网站==> 身份验证==>打开功能==>启用windows身份验证 网站设置: 博客参考: http://blo ...

  8. Androidstudio的安装与使用调试

    1安装与基本使用 1.1androidstudio的安装 1.到android-studio\bin文件夹里面,根据自己的电脑配置,打开studio.exe或者studio64.exe 2.按照向导默 ...

  9. C#命名空间 using的用法

    using的用法: 1. using指令:引入命名空间 这是最常见的用法,例如: using System; using Namespace1.SubNameSpace; 2. using stati ...

  10. PS如何批量整理图片大下

    https://jingyan.baidu.com/article/cdddd41cc7849853cb00e193.html