代码之家  ›  专栏  ›  技术社区  ›  srmark

在javascript中,如何唯一地从同一个cookiedbased sessionid下的另一个浏览器窗口标识一个浏览器窗口

  •  28
  • srmark  · 技术社区  · 15 年前

    我的Web应用程序的用户可能打开多个浏览器窗口并指向同一页。我希望页面中某些内容的状态(通过Ajax加载)在回发时保持不变。我既可以存储在cookie中,也可以存储在服务器上。不管怎样,我都想不出如何区分每扇窗户。

    例如,假设用户Bob有两个浏览器窗口打开到“某物列表”页面。每个列表都有一个 已加载的页码 我需要坚持的属性。否则,用户刷新时总是出现在第1页。Bob可能已经加载了浏览器窗口1并将其指向第5页,然后加载了浏览器窗口2并将其指向第14页。如果我只存储基于会话ID的属性,Bob如果刷新它,将在窗口1中获得第14页。

    请注意,我的状态变量实际上比这个简单的例子复杂得多,我无法坚持它们可能会导致大问题(我的应用程序中的弱点)。

    我需要某种浏览器窗口ID或其他东西。当然,它需要一个跨浏览器的解决方案(IE6+,wekbit?+,FF2+

    有什么想法吗?

    注意相关性:请记住,这对于将旧的基于表单的页面与新的支持Ajax的项目混合在一起的情况也很有用。有时,您需要回发表单,而不希望释放一些客户端状态值。

    5 回复  |  直到 6 年前
        1
  •  36
  •   Community Jaime Torres    7 年前

    您可以设置自己的窗口名,确切的语法现在会让我忘记,但您可以使用当前时间和会话ID在窗口加载时创建一个唯一的ID,然后使用该ID

    这与在javascript window.open()函数中设置名称的方式相同(但您可以对self而不是新窗口进行设置)。

    谷歌显示:

    self.window.name=myClass.getUniqueWindowID(thisSession);

    更新

    关于您需要将这个从刷新保存到刷新,我做了一些测试,它看起来是从刷新保存到刷新。使用firefox 3,在初始加载时,窗口名为空,反复按ctrl+r,窗口名被填充。然后我对设置的名称代码进行了注释并重新加载,它仍然保留了名称。

    <script type="text/javascript">
    
        alert( self.window.name );
    
        self.window.name = "blah";
    
    </script>
    

    更新

    我不得不注意到下面关于jquery的“jquery会话”插件的评论,它确实有效,提供了比这里讨论的更多的方式。

    虽然 我们还应该明确指出它依赖于HTML5的Web存储, 旧IE不支持 版本。

    企业仍然严重依赖于IE7(在巴西是“及以下”)。

    基于 self.window.name ,所有不符合HTML5的解决方案,我提供以下代码段作为跨浏览器解决方案:

    <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
    <script language="javascript" type="text/jscript">
        //----------------------------------------------------------------------
        //-- guarantees that window.name is a GUID, and that it would
        //-- be preserved whilst this window's life cicle
        //----------------------------------------------------------------------
        //-- window.name will be set to "GUID-<SOME_RANDOM_GUID>"
        //----------------------------------------------------------------------
    
        $(window).load(
            function () {
                //----------------------
                var GUID = function () {
                    //------------------
                    var S4 = function () {
                        return(
                                Math.floor(
                                        Math.random() * 0x10000 /* 65536 */
                                    ).toString(16)
                            );
                    };
                    //------------------
    
                    return (
                            S4() + S4() + "-" +
                            S4() + "-" +
                            S4() + "-" +
                            S4() + "-" +
                            S4() + S4() + S4()
                        );
                };
                //----------------------
    
                if (!window.name.match(/^GUID-/)) {
                    window.name = "GUID-" + GUID();
                }
            }
        ) //--------------------------------------------------------------------
    </script>
    

    我找到了guid函数 here (为此我提出了一些代码清理)。

        2
  •  1
  •   Herms    15 年前

    服务器随机生成一个ID,并在服务时将其存储在页面中(一些javascript变量)怎么样?然后在Ajax请求中包含该ID。它对浏览器刷新没有帮助,但是只要用户将页面留在原处(并且只让Ajax完成它的工作),它就可以正常工作。

        3
  •  1
  •   Alexis Wilke    8 年前

    这是很久以前的事了,但是今天罗伊·里科的回答帮助了我,所以我想分享我的经历。要处理页面刷新和页面backbutton的使用,我是这样做的:

    • 服务器检查浏览器是否随请求发送guid(仅适用于Ajax或表单提交)
    • 如果它不存在(浏览器刷新,backbutton),它只会返回一个带有小javascript脚本的页面。此脚本创建guid并将其放入window.name存储中,如上所述。之后,脚本创建一个guid为隐藏字段的表单,并将其提交给服务器。action属性使用与以前相同的URL(window.location.href)

    -->现在,服务器可以识别guid并根据需要传递内容。

    以下是我的代码(出于安全原因,我在服务器上创建的guid,语法“$guid来自FreeMarker,仅从服务器插入guid):

    <script>
        $(window).load(
            function () {
                if (!window.name.match(/^GUID-/)) {
                    window.name = "GUID-" + "${gUid}";
                }
                $('<form action='+window.location.href+' method="POST"><input type="hidden" name="X-GUID" id="X-GUID" value='+window.name+'></form>').appendTo('body').submit();
            }
        );  
    </script>
    

    希望能帮助别人

    顺便说一下,这种技术应该只在“非SEO页面”上使用,因为需要JavaScript来获取内容。但一般来说,SEO页面不需要标识标签会话。

    当然,现在您可以利用HTML5会话存储,但我不想依赖它,因为我还需要更老的浏览器才能正常工作。

        4
  •  0
  •   Attila    6 年前

    window.name可以被自定义的javascript库、日期计时器等覆盖。

    我建议您使用dom head元标记来存储您的ID,而不是window.name。

    <html><head><meta id="windowID" content="{YOUR ID}">
    

    页面加载后,必须通过该窗口中的Ajax加载所有内容,然后可以将此ID作为头(或数据)值附加到每个请求中。例如,在jquery中,使用以下代码:

    $(document)
        .ajaxSend(function(event, jqXHR, ajaxOptions) {
            jqXHR.setRequestHeader('windowID',
                document.getElementById('windowID').content);
    })
    

    要使用此解决方案,您必须能够访问服务器端的自定义头值。例如在Java Servlet中:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String windowName = request.getHeader("windowID");
    

    如果将分页、排序、筛选等信息存储在服务器端作为会话属性,则应将它们单独存储在单独的窗口ID-S上。

        5
  •  0
  •   Madbreaks    6 年前

    您可以使用HTML5会话存储,只需生成一个唯一的ID并将其设置在会话存储上! 每个窗口或选项卡都有自己的会话存储,这有什么酷呢? 例如:

    如果我们在3个窗口上运行以下命令:

    窗口1: sessionStorage.setItem('key' , 'window1');

    窗口2: sessionStorage.setItem('key' , 'window2');

    窗口3: sessionStorage.setItem('key' , 'window3');

    sessionStorage.getItem('key' ); <<<这将在窗口上返回相应的值!

    窗口1: sessionstorage.getitem('key'); 返回窗口1

    窗口2: sessionstorage.getitem('key'); 返回窗口2

    窗口3: sessionStorage.getItem('key'); 返回窗口3

    我相信您正在尝试保存一个变量(分别在每个选项卡/窗口上)。

    会话存储具有魅力。

    您可能面临的唯一问题是浏览器应该支持HTML5。