首页 > 代码库 > returnValue of Chrome

returnValue of Chrome

说实话,我一看到这个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);      }  </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: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);      }  </script>  <body>      <a href="javascript:openT3();">打开t3</a>      <a href="javascript:closeSelf();">关闭</a>      <a href="javascript:alert(‘点击了‘);">Chrome下点击测试</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);      }  </script>  <body>      <a href="javascript:closeSelf();">关闭</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

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

    3. 但如果子页面刷新了一下的话,即便是上面2中的情形,showModalDialog返回值也将一直是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. 但如果在子窗口中进行了刷新操作,则父窗口获取到的将是undefined,而showModalDialog后面的代码可以正常执行;
    3. 在子窗口打开情况下,虽然父窗口能够操作,但在父窗口中点击“点击刷新”后两个alert都执行了,而页面却没有刷新,说明有些特殊操作如window.location.reload();将会等到子窗口关闭后才会执行。

总结

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

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

  1. 打开子窗口情况下,还是能够操作父窗口;
  2. 子窗口在刷新后,returnValue就失效了(window.dialogArguments也变为undefined了),始终返回undefined

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

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

参考资料

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