遵循 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>
因此,如果您的选项卡应该对路径的基本级别做出react,请将参数设为“1”。因此,当 location.path() 为“/home”时,它将与href
. 如果您的选项卡应该对路径的第二层、第三层或 11 层做出react,请相应地进行调整。这种从 1 或更大的切片将绕过 href 中的邪恶“#”,它将位于索引 0 处。
唯一的要求是您调用<a>
,因为该元素假设存在一个href
属性,它将与当前路径进行比较。但是,如果您更喜欢调用<li>
或 某物,您可以很容易地适应读/写父元素或子元素。我挖掘这个是因为您可以通过简单地改变 pathLevel 参数在许多上下文中重新使用它。如果在逻辑中假设了要读取的深度,则需要多个版本的指令才能与导航的多个部分一起使用。
2014 年 3 月 18 日编辑:该解决方案没有得到充分的概括,如果您为 'activeTab' 的值定义了一个 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 上作为一个插入module使用,你可以声明为一个依赖项。如果有人真的使用它们,我很乐意将它们鲍尔化。
另外,如果你想要一个包含<li>
's的引导兼容版本,你可以使用 angular-ui-bootstrap Tabs module,我认为它是在这篇原始文章之后出现的,它可能比这个更具声明性。它对于基本内容不太简洁,但为您提供了一些附加选项,例如禁用选项卡和在激活和停用时触发的声明性事件。