遵循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
周期都会触发。
通过在指令声明中传递路径级别的参数来调用它。这指定要与href
属性匹配的当前$ location.path()中的哪个块。
<li class="nav_tab"><a href="#/home" detect-active-tab="1">HOME</a></li>
因此,如果选项卡应对路径的基本级别做出反应,则将参数设置为“ 1”。因此,当location.path()为“ / home”时,它将与中的“#/ home”相匹配href
。如果您有一些选项卡应响应路径的第二级,第三级或第十一级,请相应地进行调整。从1或更大的切片将绕过href中邪恶的“#”,该索引位于索引0。
唯一的要求是您在上调用<a>
,因为该元素假定存在href
属性,该属性将与当前路径进行比较。但是,如果您喜欢在<li>
或上进行调用,则可以轻松地进行调整以读取/写入父元素或子元素。我之所以这样做是因为您可以通过简单地更改pathLevel参数在许多情况下重用它。如果逻辑中假定要读取的深度,则您需要该指令的多个版本才能与导航的多个部分一起使用。
编辑3/18/14:解决方案的泛化不充分,如果您为undefined
针对$location.path()
和元素的返回的'activeTab'的值定义了一个arg,则该解决方案将被激活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化处理。
另外,如果您想要一个包含<li>
的兼容引导程序的版本,则可以使用 angular-ui-bootstrap Tabs模块,我认为它是在本原始帖子之后发布的,它可能比本声明更具声明性。对于基本内容来说不够简洁,但是为您提供了其他一些选项,例如禁用的选项卡以及在激活和停用时触发的声明性事件。