遵循 Pavel 使用自定义指令的建议,这是一个不需要向 routeConfig 添加任何有效负载的版本,它是超级声明性的,并且可以通过简单地更改slice()
您关注的路径来适应任何级别的路径.
app.directive('detectActiveTab', function ($location) {
return {
link: function postLink(scope, element, attrs) {
scope.$on("$routeChangeSuccess", function (event, current, previous) {
/*
Designed for full re-usability at any path, any level, by using
data from attrs. Declare like this:
<li class="nav_tab">
<a href="#/home" detect-active-tab="1">HOME</a>
</li>
*/
// This var grabs the tab-level off the attribute, or defaults to 1
var pathLevel = attrs.detectActiveTab || 1,
// This var finds what the path is at the level specified
pathToCheck = $location.path().split('/')[pathLevel] ||
"current $location.path doesn't reach this level",
// This var finds grabs the same level of the href attribute
tabLink = attrs.href.split('/')[pathLevel] ||
"href doesn't include this level";
// Above, we use the logical 'or' operator to provide a default value
// in cases where 'undefined' would otherwise be returned.
// This prevents cases where undefined===undefined,
// possibly causing multiple tabs to be 'active'.
// now compare the two:
if (pathToCheck === tabLink) {
element.addClass("active");
}
else {
element.removeClass("active");
}
});
}
};
});
我们通过监听$routeChangeSuccess
事件来实现我们的目标,而不是通过$watch
在路径上放置一个。我相信这意味着逻辑应该不那么频繁地运行,因为我认为每个$digest
周期都会触发手表。
通过在指令声明中传递路径级参数来调用它。这指定了当前 $location.path() 的哪个块你想要匹配你的href
属性。
<li class="nav_tab"><a href="#/home" detect-active-tab="1">HOME</a></li>
因此,如果您的选项卡应该对路径的基本级别做出反应,请将参数设为“1”。因此,当 location.path() 为“/home”时,它将匹配href
. 如果您有应该对路径的第二级、第三级或第 11 级作出反应的选项卡,请相应地进行调整。这种从 1 或更大的切片将绕过 href 中的恶意“#”,它位于索引 0 处。
唯一的要求是您调用 an <a>
,因为该元素假定存在一个href
属性,它将与当前路径进行比较。但是,如果您更喜欢在 or 上调用,您可以相当容易地适应读取/写入父元素或子元素<li>
。我挖掘这一点是因为您可以通过简单地改变 pathLevel 参数在许多情况下重复使用它。如果在逻辑中假设要读取的深度,则需要多个版本的指令才能与导航的多个部分一起使用。
编辑 3/18/14:该解决方案没有得到充分概括,如果您为 'activeTab' 的值定义了一个 arg,该 arg 针对undefined
和$location.path()
元素的href
. 因为:undefined === undefined
。更新以修复该情况。
在处理这个问题时,我意识到应该有一个可以在父元素上声明的版本,其模板结构如下:
<nav id="header_tabs" find-active-tab="1">
<a href="#/home" class="nav_tab">HOME</a>
<a href="#/finance" class="nav_tab">Finance</a>
<a href="#/hr" class="nav_tab">Human Resources</a>
<a href="#/quarterly" class="nav_tab">Quarterly</a>
</nav>
请注意,此版本不再类似于 Bootstrap 样式的 HTML。但是,它更现代,使用的元素更少,所以我偏爱它。这个版本的指令,加上原来的,现在可以在 Github 上作为一个插件模块使用,您可以将其声明为依赖项。如果有人真的使用它们,我很乐意对它们进行 Bower-ize。
此外,如果你想要一个包含<li>
's 的引导兼容版本,你可以使用 angular-ui-bootstrap Tabs 模块,我认为它是在这篇原始帖子之后出现的,它可能比这篇更具声明性。它对于基本的东西不太简洁,但为您提供了一些额外的选项,例如禁用的选项卡和激活和停用时触发的声明性事件。