zoukankan      html  css  js  c++  java
  • 浅析window.name属性介绍、利用window.name+隐藏iframe获取跨域数据的实现原理、应用场景(数据传递、判断是否第一次进入窗口)

    一、window下自带的 name 属性

      不知道大家有没有发现这样一种情况:在控制台里直接输出未声明变量,正常情况应该是会报错的,而且声明未赋值的变量输出应该是undefined;但是偏偏就个别特例,就是name属性。

      其实 window 自身就带有 name 这个属性,在控制台输入window可以可以看到。

      window.name直译过来是窗口名字,主要用于为超链接和表单设置目标(targets)。

      什么意思呢,我们做个案例:

    // 第一个页面
    <a href="./demo2.html" target="hello world">跳转</a>
    
    // 第二个页面
    document.write( window.name + "<br>" + name )

      我们从第一个页面跳转到第二个页面后会看到页面上有 2 个 hello world。

      这里我们就可以看出,第一个网页的a标签通过target属性将值赋值给第二个窗口的name属性,这样第二个网页的name属性就有值了。

      注意:

    1、这里提一下 window.open( strUrl , strWindowName , [strWindowFeatures] ) 的第二值也是可以给新窗口设置 window.name

    2、window.name表示当前窗口的名字,而非网页的名字,网页的名字需要使用: document.title;

    3、window.name 一般是空的字符串,他的作用其实是配合超链接和表单的target来使用的,也就是跳转时将当前窗口的信息带过去。只要这个窗口不关闭,那从这个窗口打开的其他窗口都能获得这个窗口的 window.name。

    二、window.name 跨域

      页面在浏览器端展示的时候,我们总能在控制台拿到一个全局变量window,该变量有一个name属性,其有以下特征:

    1、每个窗口都有独立的window.name与之对应;

    2、在一个窗口的生命周期中(被关闭前),窗口载入的所有页面同时共享一个window.name,每个页面对window.name都有读写的权限;

    3、window.name一直存在与当前窗口,即使是有新的页面载入也不会改变window.name的值;

    4、window.name可以存储不超过2M的数据,数据格式按需自定义。

      下面我们就验证一下同一个窗口下,页面重新载入,window.name 仍然不变

    <script>
        // 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右
        // 数据格式可以自定义,如json、字符串
        window.name = "这是a页面的内容"; 
        setTimeout(function(){
            window.location.href= b.html;
            console.log(window.name);  //"这是a页面的内容"
        },2000);
    </script>
      我们再控制台设置 name = 123,然后更换链接刷新,在到控制台看 name 还是 123。

      有时候我们的需求是在https://localhost/a.html页面内,获得"https://xxx.github.io/xxx/"上的数据,并且页面不能进行刷新。

      对于这种需求,我们不能通过window.location.href更新页面来获得数据,我们可以用一个隐藏的iframe作为中间的代理,iframe的src为"https://xxx.github.io/xxx/",在iframe页面加载完毕的时候,我们再让iframe与当前页面属于同一个域下,我们就可以拿到window.name了。

    <script>
        function load () {
            var iframe = document.getElementById('iframe');
            iframe.onload = function () {
                var window = iframe.contentWindow;
                console.log(window.name);
            }
            iframe.src = 'about:blank'; //让url地址改变,与当前页面同源,可以任意写,保持同源就好
        }
    </script>
    <iframe id="iframe" src="https://xxx.github.io/xxx/" onload="load()"></iframe>

      跨域原理:用 window.name 实现跨域,就是利用他的一个特点,就是在一个页面载入的其他页面将共享一个window.name,其他页面都有对其的读写权限,即使其他页面载入新页面,其window.name也不变。

      下面有三个页面:第一个页面放在域名localhost下

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>页面一</title>
    </head>
    <body>
        <h1>页面一</h1>
        <script>
            var iframe = document.createElement('iframe');//工具人
            iframe.style.display = "none";//工具人隐藏在背后默默付出
            var flag = false;
            iframe.onload = function () {
                if ( flag ) {
                    var data = iframe.contentWindow.name;//contentWindow.name可以拿到iframe的窗口name值
                    console.log(data);
                    iframe.contentWindow.close();//关闭隐藏的页面
                    document.body.removeChild(iframe);//删除隐藏的页面
                } else {
                    flag = true;
                    iframe.contentWindow.location = 'http://localhost/demo2.html';
    //这里因为浏览器同源策略,需要将链接改成与页面一同源的页面(也就是页面二),这里会再次触发load事件 } } iframe.src = 'http://data/data.html';//跨域,这里窗口已经拿到name,所以上面更换地址后name的值依旧存在 document.body.appendChild(iframe); </script> </body> </html>

      第二个页面是空页面,也是在localhost域名下

      第三个页面是数据页面,放在data域名下

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>data</title>
    </head>
    <body>
        <h1>数据</h1>
    <script>
        window.name = '{data:"数据"}';//将数据存到window.name里
    </script>
    </body>
    </html>

      给 隐藏iframe 赋值跨域的链接,加载完后触发load事件,此时iframe已经拿到数据放在window.name里,因为浏览器同源策略没法直接拿 iframe 的 name 值,所以将 iframe 的地址改成同域名下的一个网页,在用 contentWindow 方法获取 iframe 的 name 值拿数据。

    三、应用场景

      总体感觉应用场景不多,下面这 2 个场景使用还不错:

    1、利用 window.name 进行页面间的数据传递,这个就不多说了,具体情况具体考虑吧;

    2、Window.name 判断页面是第一次进入还是刷新

      之前公司有个需求,扣费信息在第一次进入页面窗口弹出,若用户刷新此页面窗口则不应该弹出消费信息。使用cookie不能满足这个需求,因为如果用户打开第二个窗口,也是需要第一次弹出扣费信息。觉得windw name属性比较合适又很简单,可以用于区分页面是第一次进来还是刷新。

    if ( !window.name ) { // 第一次进页面
      window.name="myname";
    } else{ // 非第一次进页面
      document.getElementById("div").style.display = 'none'; // 隐藏
    }

      这样,各个页面窗口不互相影响,即使新开两个页面,也能独立记录是否第一次进入页面,还是刷新。

      有其他妙用欢迎不吝赐教。

  • 相关阅读:
    关于json的一些自己的了解
    .Net Core 控制台 使用Topshelf 加入DI(服务注册)
    【Linux】Centos7 入门到放弃记录
    【git】.net core +git减少包体积
    【git-bug累计】实践中git命令出现的问题总结
    [Bug] uni-app 上下切屏tabbar底部导航显示问题
    .NetCore2.0 vue-element-admin 出现的错误记录
    黑盒测试总结
    sql 学习笔记
    Linux 学习笔记
  • 原文地址:https://www.cnblogs.com/goloving/p/15387233.html
Copyright © 2011-2022 走看看