【问题标题】:Store browser tab specific data存储浏览器选项卡特定数据
【发布时间】:2012-09-19 00:17:21
【问题描述】:

我有一个 Web 应用程序,它存储有关最近访问的页面的信息,我们称它们为 A。当用户访问另一种称为 B 的页面类型时,我会在顶部呈现一个菜单,其中包含一个指向最近访问的 A 的按钮-页。 B 页面可以通过 A 页面或 B 页面访问,并且可以被用户视为 A 的属性。

这很好用,但是当有人打开两个选项卡并且在选项卡 1 中的 B 页面上带有指向 A 页面 A1 的链接时,他们会打开一个新选项卡并访问 A 页面 A2,这会成为问题。当用户然后刷新选项卡 1 中的 B 页面时,菜单更改为 A2。我希望能够识别正在使用的选项卡,以便我可以为选项卡 1 保存 A1,这样它就不会更改为 A2。

使用一个标签时:

A1 -> B1 -> B2 (the menu points back to A1)

使用两个选项卡时:

Time            | T1       | T2       | T3          
----------------+----------+----------+-------------
Tab 1:          | A1 -> B1 |          | [refresh B1]
Tab 2:          |          | A2 -> B3 |             
----------------+----------+----------+-------------
Menu points to: | A1    A1 | A2    A2 | A2

当用户返回选项卡 1 时,这会混淆他们在选项卡 2 (A2) 而不是 A1 中查看的用户。

恐怕无法获取浏览器标签 ID,但有人可能有任何解决方法的想法?

【问题讨论】:

    标签: javascript jquery django local-storage browser-tab


    【解决方案1】:

    HTML5 sessionStorage 解决了这个问题:

    站点可以将数据添加到会话存储中,并且该窗口中打开的同一站点的任何页面都可以访问这些数据。

    supported by all modern browsers

    另一种方法是使用window.name 属性。它是特定于选项卡/窗口的,并且在浏览器导航中保持不变。因此,您可以在 window.name 属性中存储一些标签 ID 之王

    【讨论】:

    • window.name 属性效果很好,它是一个很好的解决方案,可以在每个浏览器选项卡中存储一个简单的数据!
    【解决方案2】:

    编辑:时间的流逝使我从 2012 年开始的原始答案不正确。正如bedrin 指出的那样,您现在可以使用Window.sessionStorage object

    sessionStorage 属性允许您访问当前源的会话存储对象。 sessionStorage 与 Window.localStorage 类似,唯一的区别是 localStorage 中存储的数据没有设置过期时间,而 sessionStorage 中存储的数据在页面会话结束时会被清除。只要浏览器打开并在页面重新加载和恢复后仍然存在,页面会话就会持续。在新选项卡或窗口中打开页面将导致启动新会话,这与会话 cookie 的工作方式不同。

    原答案(2012 年):

    恐怕这无法以可移植的方式实现,因为您发现自己无法检索浏览器标签 ID 之类的内容。据我所知,HTML 标准完全不知道浏览器中的选项卡。

    我能想到的唯一解决方法是:在您的应用程序中实现和管理选项卡。我见过几个业务网络应用程序可以做到这一点,但是(恕我直言)用户体验非常糟糕。

    【讨论】:

    • 太糟糕了...我已经开始研究一个非 100% 可靠的解决方案,因为我担心你是对的。
    【解决方案3】:

    所以我做了一个解决方案似乎效果很好不。请参阅最后一个问题项目符号。我仍然希望有更好的想法,所以如果你继续的话,请告诉我!

    无论如何;这就是我的做法。请记住,这不是一个 100% 万无一失的解决方案,如果用户“行为不端”并同时刷新多个标签,它可能会感到困惑:

    base.html(所有页面都继承)({{ A }} 呈现来自 Django 的变量):

    // This is executed right before leaving the page
    window.onunload = function() {
        if( '{{ A }}' != null ) 
            var prev_A = '{{ A }}';
        else if (typeof previous_A != 'undefined') {
            var prev_A = previous_A;
        else 
            var prev_A = '';
        localStorage.setItem('a', prev_A);
    };
    // Remove the local storage as soon as you get to this page
    localStorage.removeItem('a');
    

    B_base.html(所有B的基础模板。B_base.html也继承了base.html。我把这段代码放在base.html代码之前执行)

    var previous_A = localStorage.getItem('a');
    

    所以基本上我得到的是每个页面在离开页面时设置localStorage'a'并在进入页面时立即删除localStorage'a',除了首先保存'a'的B页面在删除之前作为局部变量。

    问题:

    • 同时在多个选项卡中打开链接将覆盖此变量,并且一个选项卡将没有 previous_A。
    • 不去任何地方关闭一个A标签,然后直接打开一个新的B页面会导致B标签的previous_A中有关闭的A的值。
    • 在 A 页面的新选项卡中打开 B 链接不会给他们返回链接...这是破坏者。

    【讨论】:

    • 恕我直言,从技术角度来看,这是一个有趣的 hack,但从可用性角度来看,这不是一个好主意。良好的 UI 设计除了其他方面外,还在于最大限度地减少令人惊讶和不一致的行为。而且您描述的问题似乎不容易被普通用户记住(因此避免)。
    • 不,你是对的,我测试了一段时间后再次删除了它。因为它不能像用户预期的那样 100% 工作,所以它对我没有用。