更佳的可链接选项卡

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200美元免费额度!

我发现对于“选项卡”设计模式,人们通常希望有一种方法可以链接到特定的选项卡。例如,您可以向某人提供一个 URL,该 URL 会将他们引导至该页面,并激活所需的特定选项卡,并显示正确的内容。

如果每个选项卡都是一个完全不同的 URL,则很容易。在提供的 HTML 中,将相应的类名应用于选项卡以使其看起来处于活动状态,并在下方提供相应的内容。

Wufoo 在应用内使用选项卡设计模式。每个选项卡都是一个完全不同的页面和 URL。

如果这些选项卡是“同一页面”选项卡,可以即时(或通过 Ajax)隐藏/显示不同的内容面板,则会稍微复杂一些。对此的一种常见(我认为是语义化的)方法是使用哈希链接,例如:

http://example.com/#tab-three
此类选项卡可能是“同一页面”选项卡,本身没有唯一的 URL

使用 CSS3 的 :target 伪类选择器,可以通过 CSS 独自创建功能性 选项卡区域(无需 JavaScript)。但是,如果目标是纯 CSS 选项卡,这更好

尽管我尝试过使用 CSS 技术,但我认为功能性选项卡区域最好由 JavaScript 来处理。这是功能领域,如果我们遵循传统的关注点分离模型,则应由 JavaScript 处理。

哈希链接还存在其他一些问题

  1. 当页面加载带有哈希链接哈希链接发生更改时,浏览器将向下滚动,以便该哈希的 ID 所对应的元素位于页面顶部。很有可能这不是我们想要的。后者很容易使用 preventDefault() 来解决。前者几乎不可能干净地处理。
  2. 更改页面的哈希标签会向浏览器历史记录中添加一个条目,因此按下后退按钮将返回到之前的哈希。也有可能这不是我们想要的。

让我们同时解决这两个问题,并满足能够链接到特定选项卡的需求。这就是我们要做的

  1. 不使用哈希链接,而是使用 URL 参数(无向下跳转)。
  2. 使用超酷的 history.replaceState(),这样我们就可以更改 URL 而不影响后退按钮。

我们的 URL 将类似于

http://example.com/?tab=tab-three

与其从头重写基于 JavaScript 的选项卡,不如使用我现有的 Organic Tabs 演示。我们只需要调整插件的极少量内容即可使其工作。我们将添加一个 param 参数,以便人们可以在其中选择他们想要的任何内容。

$.organicTabs.defaultOptions = {
    "speed": 300,
    "param": "tab"
};

然后在包含所有选项卡更改功能的部分中,我们将添加这一行

// Change window location to add URL params
if (window.history && history.pushState) {
  // NOTE: doesn't take into account existing params
	history.replaceState("", "", "?" + base.options.param + "=" + listID);
}

棘手的是,我们需要在页面加载时提取 URL 参数并使用 JavaScript 对其进行处理。这意味着我们需要使用服务器端语言,并将其与我们的 JavaScript 混合在一起。这里我将使用 PHP

更新:我们可以完全通过 JavaScript 访问查询字符串,并 轻松解析各个部分。因此,我们将使用以下代码代替以前位于此处的 PHP 代码(由于许多原因,它并不理想)

var queryString = {};
window.location.href.replace(
    new RegExp("([^?=&]+)(=([^&]*))?", "g"),
    function($0, $1, $2, $3) { queryString[$1] = $3; }
);

if (queryString[base.options.param]) {

	var tab = $("a[href='#" + queryString[base.options.param] + "']");

	tab
		.closest(".nav")
		.find("a")
		.removeClass("current")
		.end()
		.next(".list-wrap")
		.find("ul")
		.hide();
	tab.addClass("current");
	$("#" + queryString[base.options.param]).show();
      
};

此代码获取该 URL 参数,并确保突出显示当前选项卡并显示正确的内容。

功能演示

查看演示   下载文件

视频

不完整

history.replaceState(以及所有 历史管理内容)的浏览器支持 远非普遍。我在这里使用了一个基本的特性测试,但没有实现任何回退。重要的部分,即选项卡功能,仍然可以正常工作。您可能需要做更多的事情。

我也没有考虑现有的 URL 参数。如果您的页面已经在使用它们,并且您还想使用此功能(例如 ?foo=bar&tab=tab-one),这将变得更加复杂。您可能需要获取整个 URL 参数字符串并将其传递给插件。然后在使用 replaceState() 时将其解析并重新插入现有参数。