32

我的 Web 应用程序的用户可能打开了多个浏览器窗口并指向同一页面。我希望在回发中保留页面中某些事物的状态(通过 ajax 加载)。我既可以存储在 cookie 中,也可以存储在我的服务器上。无论哪种方式,我都想不出如何区分每个窗口。

例如,假设用户 Bob 有两个浏览器窗口打开到 ListOfSomething 页面。每个列表都有一个我需要保留的LoadedPageNumber属性。否则,用户在刷新时总是在第 1 页结束。Bob 可能已加载浏览器窗口 1 并将其指向第 5 页,然后加载浏览器窗口 2 并将其指向第 14 页。如果我仅根据会话 id 存储属性,则 Bob 将在窗口 1 中刷新第 14 页。

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

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

有任何想法吗?

关于相关性的注意事项:请记住,这对于您将基于旧表单的页面与启用了 AJAX 的新项目混合的情况也很有用。有时您需要回发表单并且您不想丢失一些客户端状态值。

4

6 回答 6

39

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

这将与您在 javascript window.open() 函数中设置名称的方式相同,(但您可以对自己执行此操作,而不是新窗口)

谷歌搜索显示:

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-session' 插件的评论,它确实有效并且提供的方式比这里讨论的要多。

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

企业仍然严重依赖 IE 7(在巴西这里是“及以下”)。

基于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 函数(为此我提出了一些代码清理)。

于 2009-05-14T18:34:50.653 回答
2

您可以使用 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

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

sessionStorage 很有魅力。

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

于 2017-02-16T13:53:02.847 回答
1

让您的服务器随机生成一个 ID 并在提供该 ID 时将其存储在页面(一些 javascript 变量)中怎么样?然后只需在 ajax 请求中包含该 ID。它不会帮助刷新浏览器,但只要用户将该页面留在原处(并且只是让 ajax 的东西做它的事情)它应该可以正常工作。

于 2009-05-14T18:36:14.457 回答
1

很久以前了,但是今天Roy Rico的回答对我有帮助,所以我想分享一下我的经验。为了处理页面刷新和页面后退按钮的使用,我这样做:

  • 您的服务器检查浏览器是否将 GUID 与他的请求一起发送(仅适用于 ajax 或表单提交)
  • 如果它不存在(浏览器刷新、后退按钮),它只会发回一个带有小 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 会话存储,但我不想依赖它,因为我还需要旧版浏览器才能正常工作。

于 2016-02-29T14:00:09.953 回答
0

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

而不是 window.name 我建议您使用 DOM 头元标记来存储您的 id

<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。

于 2018-04-13T09:34:59.427 回答
0

事实上,使用新的Web Locks API,您可以获得实际的内部窗口 ID(又名clientId)。LockManager.query()可以提供有关持有锁的信息,包括所有者的 ID。由于安全限制,可能无法在某些 iframe 上下文中工作,但在顶部窗口中通常应该是好的。

function getCurrentWindowId() {
    return new Promise((resolve) => {
        let lockName;
        tryGetLock(); // one attempt should almost always be enough

        function tryGetLock() {
            // generate some random lock name
            lockName = 'get-self-id-' + (Math.random() * 0xffffffff >>> 0);
            navigator.locks.request(lockName, { mode: 'exclusive', ifAvailable: true }, withLock);
        }

        function withLock(lock) {
            // unsing setTimeout(0) here to execute client's code after releasing the lock
            if (lock)
                return navigator.locks.query()
                    .then(({ held }) => held.find(lock => lock.name === lockName).clientId)
                    .then(clientId => setTimeout(resolve, 0, clientId));
            else {
                // unlucky - just try another lock
                setTimeout(tryGetLock, 0);
                return Promise.resolve();
            }
        }
    });
}

//usage

getCurrentWindowId().then(clientId => {
   // do something with id
});

可在 Firefox 96 和 Chrome 97 中运行。为了获得应该随时可用的信息而做出如此笨拙的结构感觉很丢脸。

于 2022-02-04T16:23:03.913 回答