emberjs - 如何使用路由器基础设施标记活动菜单项
Posted
技术标签:
【中文标题】emberjs - 如何使用路由器基础设施标记活动菜单项【英文标题】:emberjs - how to mark active menu item using router infrastructure 【发布时间】:2012-07-22 15:08:22 【问题描述】:我正在尝试创建导航标签(取自Twitter Bootstrap):
<ul class="nav nav-tabs">
<li class="active"><a href="#">Home</a></li>
<li><a href="#">Profile</a></li>
<li><a href="#">Messages</a></li>
</ul>
活动标签标有class="active"
。
http://jsfiddle.net/schawaska/pfbva/ 有一个很好的静态导航栏和路由器/插座功能示例,但是 我不明白如何创建动态导航栏/菜单/选项卡视图。
据我了解,可以在每个菜单项中使用类绑定:
classNameBindings: ['isActive:active']
但是切换 isActive 属性的正确位置在哪里?
【问题讨论】:
仅供参考:在新路由器中,linkTo
自动提供此行为 -- emberjs.com/guides/routing/defining-your-routes
【参考方案1】:
Ember 1.11+:
#link-to "dashboard" tagName="li"
<a href="view.href">Dashboard</a>
/link-to
Ember bind-attr):
#link-to "dashboard" tagName="li"
<a bind-attr href="view.href">Dashboard</a>
/link-to
【讨论】:
这必须是公认的答案。我只花了 10 分钟试图在 标记上获取bindAttr
以按名称引用 view.href,直到我找到它并意识到我把它全部倒退了。
这绝对是最简单的方法
绝对是我在小组中找到的最佳答案。
这绝对是最简单的方法!应该是公认的答案。
在链接元素上时,您需要明确地将光标设置为指针:a cursor: pointer;
请参阅marceldegraaf.net/2013/05/17/…【参考方案2】:
如果您使用的是 Ember >= 1.11,那么下面的 https://***.com/a/14501021/65542 是正确答案。
我会创建一个NavigationView
,参见http://jsfiddle.net/pangratz666/z8ssG/:
车把:
<script type="text/x-handlebars" data-template-name="navigation">
<ul class="nav nav-tabs">
#view view.NavItemView item="home"
<a action gotoHome >Home</a>
/view
#view view.NavItemView item="profiles"
<a action gotoProfiles >Profiles</a>
/view
#view view.NavItemView item="messages"
<a action gotoMessages >Messages</a>
/view
</ul>
</script>
JavaScript:
App.NavigationView = Em.View.extend(
templateName: 'navigation',
selectedBinding: 'controller.selected',
NavItemView: Ember.View.extend(
tagName: 'li',
classNameBindings: 'isActive:active'.w(),
isActive: function()
return this.get('item') === this.get('parentView.selected');
.property('item', 'parentView.selected').cacheable()
)
);
在您的路线connectOutlets
中,您必须通过router.set('navigationController.selected', 'home');
设置当前导航项...
还可以查看 ember-bootstrap 存储库,它在 Ember.js 中包装了 Bootstrap 的这个和更多功能
【讨论】:
您能否更新您的答案以反映新路由器的变化?查看***.com/questions/14328295/…。 非常感谢@pangratz。你是摇滚明星。 如果你想改变标签而不改变 url 怎么办? (同时仍然使用路由器访问选项卡,例如/wizards/:wizard_id/edit
,并且在向导中有 3 个步骤可以编辑,您不想更改 URL。)
FWIW,我更新了 pangratz 的示例,如图所示 jsfiddle
@bazzel:不幸的是,这不再起作用了。【参考方案3】:
上面的一些建议对于 twitter bootstrap 案例仍然有效。你也可以试试这样的
#link-to 'dashboard' tagName='li'
#link-to 'dashboard'Link Title/link-to
/link-to
link-to
和 li
tagName 将活动类应用于 li
内部link-to
将是一个anchor
元素,当您单击鼠标右键时,它会为您提供Open in New Tab
功能
【讨论】:
这就是我们所做的,非常适合 TWBS 标签【参考方案4】:最近有一个 Ember-cli 插件可用于执行此操作。它被称为ember-cli-active-link-wrapper。
安装:ember install ember-cli-active-link-wrapper
你可以这样使用它:
#active-link
link-to "Index" "index"
/active-link
导致:
<li class='active'>
<a href="/" class='active'>Index</a>
</li>
【讨论】:
这确实应该是公认的答案。在现代 Ember 中,所有支持率较高的都已损坏或无法维护。【参考方案5】:我知道这是旧帖子,但这里是 Ember 2.4.0
的更新为了创建链接,你可以写
#link-to 'photoGallery'
Great Hamster Photos
/link-to
或
link-to 'Great Hamster Photos' 'photoGallery'
当当前路由与链接的路由匹配时,Ember 会自动将类设置为活动状态(在此示例中为 photoGallery
)。
如果您也想控制其他路由上的“活动”类,可以通过设置current-when
属性来实现。
#link-to 'photoGallery' current-when='photoGallery photoPreview'
Great Hamster Photos
/link-to
此链接将在 photoGallery
和 photoPreview
路由上都有 active
类。
https://github.com/emberjs/ember.js/blob/v2.4.0/packages/ember-routing-views/lib/components/link-to.js#L140
【讨论】:
【参考方案6】:车把
<ul class="nav">
<li>#linkTo "index"Index/linkTo</li>
<li>#linkTo "about"About/linkTo</li>
</ul>
App.Router.map(function()
this.route("about");
);
它会根据路由自动添加活动类。 注意:使用 ember-1.0.0-pre.4.js 测试
【讨论】:
这行得通,我遇到的唯一问题是它没有在我的根链接上设置默认值。我将我的索引模板呈现给我的“介绍”控制器,但这并没有在链接上设置类。知道该怎么做吗?【参考方案7】:你也可以把 isActive 方法改成这样:
isActive: function()
return App.getPath('router.currentState.path') === "root.firms";
.property("App.router.currentState"),
或
isActive: function()
return this.get('controller.target.currentState.path') === "root.firms";
.property("controller.target.currentState"),
【讨论】:
【参考方案8】:我看到这个问题很老了,但是如果你将 Ember.js 升级到 RC3,你可以使用tagName
属性,比如:
#link-to messages tagName="li"Messages/link-to
这里是 API - http://emberjs.com/api/classes/Ember.LinkView.html
【讨论】:
【参考方案9】:不确定它是否非常动态,但请尝试在http://codebrief.com/2012/07/anatomy-of-an-ember-dot-js-app-part-i-redux-routing-and-outlets/ 上查看解决方案 主要思想是检查您的应用程序的状态
JavaScript:
function stateFlag(name)
return Ember.computed(function()
var state = App.router.currentState;
while(state)
if(state.name === name) return true;
state = state.get('parentState');
return false;
).property('App.router.currentState');
ApplicationController: Ember.Controller.extend(
isHome: stateFlag('home'),
isSections: stateFlag('sections'),
isItems: stateFlag('items')
)
车把:
<li class="home" bindAttr class="isHome:active">
</li>
<li class="sections" bindAttr class="isSections:active">
</li>
<li class="items" bindAttr class="isItems:active">
</li>
更新: pangratz 的解决方案看起来更漂亮
【讨论】:
【参考方案10】:这是一个完整的工作解决方案:
查看:
App.NavView = Ember.View.extend(
tagName: 'li',
classNameBindings: ['active'],
active: function()
return this.get('childViews.firstObject.active');
.property()
);
模板:
<ul>
#each item in controller
#view App.NavView
#linkTo "item" item tagName="li"
<a bindAttr href="view.href">
item.name
</a>
/linkTo
/view
/each
</ul>
【讨论】:
【参考方案11】:从 v0.8.0 ember-bootstrap 开始支持导航,包括正确处理活动状态。而且没有任何链接到/标签名称的黑客:
#bs-nav type="pills"
#bs-nav-item
#link-to "foo"Foo/link-to
/bs-nav-item
#bs-nav-item
#link-to "bar"Bar/link-to
/bs-nav-item
/bs-nav
见http://kaliber5.github.io/ember-bootstrap/api/classes/Components.Nav.html
【讨论】:
【参考方案12】:这里提出的许多解决方案不适用于任何最新的 Ember 版本(例如,视图被弃用)。此外,仅使用 link-to
帮助程序不会解决问题,因为引导程序希望 active
类出现在 <li>
而不是 <a>
!
所以我将尝试总结目前确实有效的解决方案:
使用ember-cli-active-link-wrapper
插件为此特殊用例提供了一个组件:
<ul class="nav nav-tabs">
#active-link
#link-to "foo"Foo/link-to
/active-link
#active-link
#link-to "bar"Bar/link-to
/active-link
</ul>
取自https://***.com/a/29939821/5556104
使用ember-bootstrap
ember-bootstrap 提供了许多将引导功能集成到您的 ember 应用程序中的组件,其中包括导航组件:
#bs-nav type="tabs"
#bs-nav-item
#link-to "foo"Foo/link-to
/bs-nav-item
#bs-nav-item
#link-to "bar"Bar/link-to
/bs-nav-item
/bs-nav
取自https://***.com/a/38279975/5556104
链接到黑客
有点老套,但应该可以在没有任何附加插件的情况下工作:
<ul class="nav nav-tabs">
#link-to "foo" tagName="li"
#link-to "foo"Foo/link-to
/link-to
#link-to "bar" tagName="li"
#link-to "bar"Bar/link-to
/link-to
</ul>
取自https://***.com/a/23966652/5556104
【讨论】:
【参考方案13】:迟早要更改您的状态的命名或您必须通过代码和视图的任何内容,还为每条路线添加一个函数似乎是不可取的。 我的方法更加程序化和模块化:
# Parent View-Tamplate, holding the navbar DOM elements
App.NavView = Ember.View.extend(
controller: App.NavArrayController
templateName: "ember-nav"
)
# We push NavItems into this array
App.NavArrayController = Ember.ArrayController.create(
content: Ember.A([])
)
# NavItem has two settable properties and
# an programmatic active state depending on the router
App.NavItem = Ember.Object.extend(
title: ''
goto: null # <=this is the name of the state we want to go to!
active: (->
if App.router.currentState.name == @.get "goto"
true
else
false
).property('App.router.currentState.name').cacheable()
)
# the actual NavElement which gets the class="active" if the
# property "active" is true, plus a on-click binding to
# make the Router transition to this state
App.NavItemView = Ember.View.extend(
tagName: "li"
classNameBindings: ["active"]
click: ->
App.router.transitionTo(@get('goto'))
false
)
nav-view.hbs(用于 twitter-bootstrap 风格的导航)
<div class="nav-collapse collapse">
<ul class="nav">
#each App.NavArrayController
#view App.NavItemView classBinding="active" gotoBinding="goto"
<a href="#" bindAttr data-goto="goto"> title</a>
/view
/each
</ul>
</div>
这样,我可以在路由器中创建和处理我的路由, 并排保持导航定义:
# put this somewhere close to the Router
App.NavArrayController.pushObjects(
[
App.NavItem.create(
title: 'Home'
goto: 'home'
),
App.NavItem.create(
title: 'Chat'
goto: 'chat'
),
App.NavItem.create(
title: 'Test'
goto: 'test'
)
]
)
【讨论】:
【参考方案14】:上面 baijum 的回答大部分是正确的,但是在最新版本的 Ember 中,“bind-attr”已被弃用。下面是新的写法:
#link-to "dashboard" tagName="li"
<a href="view.href">Dashboard</a>
/link-to
如您所见,它更简单,而且有点像魔术......
【讨论】:
【参考方案15】:正如其他人所说,使用#link-to
链接到现有的route
,当该路由是当前URL 时,#link-to
会自动将active
添加到其CSS 类中。
见Ember issue 4387
【讨论】:
以上是关于emberjs - 如何使用路由器基础设施标记活动菜单项的主要内容,如果未能解决你的问题,请参考以下文章
Vue JS:如何在路由器链接中设置活动 <a> 标记的样式?