javascript Ember.js 锚链接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18445661/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ember.js anchor link
提问by eddie.vlagea
I have a login box on homepage that I need to link to. The login box has id="login
" in html and I have a link to it like this <li><a href="#login">Login</a></li>
so on click it takes me to that login div but when I hit refresh or go directly to the link with anchor I get Uncaught Error: No route matched the URL 'login'
我在主页上有一个登录框,我需要链接到它。登录框id="login
在 html中有" 并且我有一个像这样的链接<li><a href="#login">Login</a></li>
所以单击它会将我带到该登录 div 但是当我点击刷新或直接转到带有锚点的链接时我得到Uncaught Error: No route matched the URL 'login'
Anybody has any ideas how I can accomplish this simple task in Ember? Thanks.
有人对我如何在 Ember 中完成这个简单的任务有任何想法吗?谢谢。
Update
更新
Here's how my code looks like:
我的代码如下所示:
The navigation
导航
<ul class="nav navbar-nav pull-right">
<li><a href="#login">Signup</a></li>
<li>{{#linkTo 'about'}}About{{/linkTo}}</li>
</ul>
and somewhere below on the page I have
在页面下方的某个地方我有
<section id="login">
-- some content
</section>
采纳答案by kroofy
Query Params
查询参数
Updated answer based on the Query Params approach (currently featured flag as of Dec 21 2013)
基于查询参数方法更新的答案(截至 2013 年 12 月 21 日的当前特色标志)
Based on alexspellersoriginal JSFiddle, complete demo can be found here: http://jsfiddle.net/E3xPh/
基于alexspellers 的原始 JSFiddle,完整的演示可以在这里找到:http: //jsfiddle.net/E3xPh/
In your Router
, add support for query params
在您的Router
, 添加对查询参数的支持
App.Router.map ->
@resource 'index', path: '/', queryParams: ['anchor']
Using the Route
of your choice, setup a property for the anchor
query param in the setupController
method.
使用Route
您选择anchor
的setupController
方法,为方法中的查询参数设置一个属性。
App.IndexRoute = Em.Route.extend
setupController: (controller, context, queryParams) ->
controller.set 'anchorLocation', queryParams.anchor
Finally in your Controller
make an observer for the anchorLocation
property.
最后在你Controller
做一个观察者的anchorLocation
财产。
App.IndexController = Em.ArrayController.extend
showAnchor: (->
$elem = $(@anchorLocation)
$scrollTo = $('body').scrollTop($elem.offset().top)
).observes 'anchorLocation'
Now you can use the following code in your templates to scroll to an anchor or point your browser to /#/?anchor=#login
for example.
现在,您可以在模板中使用以下代码滚动到锚点或将浏览器指向/#/?anchor=#login
例如。
{{#linkTo anchor='#login'}}Show login{{/linkTo}}
Simple action approach
简单的动作方法
Possible answer based on what you wrote in the comments to the first answer. Hacked together something simple here.
可能的答案基于您在第一个答案的评论中所写的内容。在这里拼凑一些简单的东西。
Clicking the Index link takes you to the IndexRoute and scrolls you to the login box, however the URL is not reflecting this change and typing #login will not work either.
单击 Index 链接会将您带到 IndexRoute 并将您滚动到登录框,但是 URL 未反映此更改,并且键入 #login 也不起作用。
App.ApplicationRoute = Ember.Route.extend({
events: {
goToLink: function(item, anchor) {
var $elem = $(anchor);
var $scrollTo = $('body').scrollTop($elem.offset().top);
this.transitionToRoute(item.route).then($scrollTo); //.transitionTo is depricated
}
}
});
Instead of using linkTo, you will use goToLink in your template when you want to scroll to an anchor.
当您想要滚动到锚点时,您将在模板中使用 goToLink,而不是使用 linkTo。
<ul>
<li><a href="#/" {{action goToLink "index" "#login"}}>Index</a></li>
<li>{{#linkTo about}}About{{/linkTo}}</li>
<li>{{#linkTo contact}}Contact{{/linkTo}}</li>
</ul>
回答by mavilein
The problem is that Ember used the hash part in the URL to store the current state of your application. Spontaneously i see two possible solutions.
问题是 Ember 使用 URL 中的哈希部分来存储应用程序的当前状态。我自然而然地看到了两种可能的解决方案。
1 -*Don't let Ember use the hash part of your URLs.* Therefore use the HTML5 historylocation implementation of Ember. This will result in URLs like yourdomain.com/users/1/
without #
.
1 -*不要让 Ember 使用您的 URL 的哈希部分。* 因此使用Ember的HTML5 历史定位实现。这将导致像yourdomain.com/users/1/
没有#
.
App.Router.reopen({
location: 'history'
});
2 - Don't use this technique. Instead use jQueryto do the scrolling to the relevant part. This could look like this:
2 - 不要使用这种技术。而是使用 jQuery滚动到相关部分。这可能是这样的:
<ul class="nav navbar-nav pull-right">
<li><a {{action jumpToLogin}}>Signup</a></li>
<li>{{#linkTo 'about'}}About{{/linkTo}}</li>
</ul>
And in the corresponding view:
并在相应的视图中:
App.YourView = Ember.View.extend({
jumpToLogin : function(){
$('html, body').animate({
scrollTop: $("#login").offset().top
}, 2000);
}
});
This may seem a lot of code for this small feature, but i guess this is a nicer user experience right? Actually you can improve this approach by extracting this logic into a mixin, so you don't have to repeat it over and over:
对于这个小功能,这似乎有很多代码,但我想这是一个更好的用户体验,对吧?实际上,您可以通过将此逻辑提取到 mixin 来改进此方法,因此您不必一遍又一遍地重复:
App.ScrollToMixin = Ember.Mixin.create({
scrollDuration : 2000, //default
scrollTo : function(selector){
$('html, body').animate({
scrollTop: $(selector).offset().top
}, this.get("scrollDuration");
)
});
// mix it into your View
App.YourView = Ember.View.extend(App.ScrollToMixin, {});
And use it in your template:
并在您的模板中使用它:
<ul class="nav navbar-nav pull-right">
<li><a {{action scrollTo "login"}}>Signup</a></li>
<li>{{#linkTo 'about'}}About{{/linkTo}}</li>
</ul>
PS:I haven't tested the code with the mixin. I am not absolutely sure wether the String "login" gets passed to the action handler exactly like that. So you would have to test :-)
PS:我没有用mixin测试代码。我不确定字符串“登录”是否完全像那样传递给动作处理程序。所以你必须测试:-)
回答by knownasilya
I use a component, which could also be extended to support query params via an action.
我使用了一个组件,该组件也可以通过操作进行扩展以支持查询参数。
var ScrollToComponent = Ember.Component.extend({
tagName: 'a',
anchor: '',
scrollTo: function () {
var anchor = this.get('anchor'),
$el = Ember.$(anchor);
if ($el) {
Ember.$('body').scrollTop($el.offset().top);
}
}.on('click')
});
This is how you'd use it:
这是你使用它的方式:
{{#scroll-to anchor=anchor}}Jump To Anchor{{/scroll-to}}
Where anchor
is #my-id
.
哪里anchor
是#my-id
。
Edit
编辑
Here's an ember-cli addon that does this https://www.npmjs.com/package/ember-scroll-to
这是一个执行此操作的 ember-cli 插件https://www.npmjs.com/package/ember-scroll-to
回答by Jesse Sanford
The problem with most of the previous answers is that if the route does not change when clicking on a "link" with a "href hash/fragment/id" in it then the ember router will not fire the hooks necessary to perform most of previous solutions.
大多数先前答案的问题是,如果单击带有“href hash/fragment/id”的“链接”时路由没有改变,那么 ember 路由器将不会触发执行大部分以前的钩子解决方案。
This is evident in pages with multiple "headings" where you want to allow a user to jump from a "nav/index or list of links" to the relevant section of the page (like on terms of service or about pages).
这在具有多个“标题”的页面中很明显,您希望允许用户从“导航/索引或链接列表”跳转到页面的相关部分(如服务条款或关于页面)。
In these situations ember requires that you "opt into a full transition" so that the router will fire it's hooks even though the route has not changed but the query params have. See "opting into a full transition"for more information.
在这些情况下,ember 要求您“选择完全转换”,以便即使路由没有更改但查询参数已更改,路由器也会触发它的钩子。有关更多信息,请参阅“选择完全过渡”。
NOTE: The only documentedhook that will be fired when using this "opt in" is the model hook.
注意:使用此“选择加入”时将触发的唯一记录挂钩是模型挂钩。
I believe that this "full transition" opt-in was only intended to be used when refreshing models on query param change for things like sorting or filtering.
我相信这种“完全转换”选择仅用于在查询参数更改时刷新模型以进行排序或过滤等操作。
Admittedly this seems like a bit of a hack, but the above "opt-in" can be used for scrolling to our div /anchor tag in question. In the future the opt-in might be able to fire other more appropriate hooks as well (setupController specifically would be nice).
诚然,这看起来有点像黑客,但上面的“选择加入”可用于滚动到我们有问题的 div /anchor 标签。将来,选择加入也可能会触发其他更合适的钩子(特别是 setupController 会很好)。
Also In case anyone else is googling. I also tried using the "willTransition" and "didTransition" actions on the route as well. While they did get fired when transitioning from other routes sadly they also fail to fire when transitioning from the same route to itself.
也以防其他人在谷歌上搜索。我还尝试在路线上使用“willTransition”和“didTransition”动作。虽然他们在从其他路线转换时确实被解雇了,但遗憾的是,他们在从同一路线转换到自身时也未能触发。
Finally it should be obvious to some (but wasn't for me at first) that in order to get the browser to scroll to the id in question the dom will need to be fully loaded. So we have to perform the scroll inside the Ember.run.schedule('afterRender',
callback.
最后,对于某些人来说应该很明显(但一开始并不适合我),为了让浏览器滚动到有问题的 id,dom 需要完全加载。所以我们必须在Ember.run.schedule('afterRender',
回调中执行滚动。
FYI I am using the latest ember-cli, ember.js and ember-data generally available at the moment:
仅供参考,我正在使用目前普遍可用的最新 ember-cli、ember.js 和 ember-data:
- ember-cli: 1.13.7
- ember: 1.13.6
- ember-data: 1.13.7
- 余烬cli:1.13.7
- 余烬:1.13.6
- 余烬数据:1.13.7
app/router.js
应用程序/router.js
this.route('about', {
queryParams: ['anchor']
});
routes/about.js
路线/about.js
import Ember from 'ember';
export default Ember.Route.extend({
queryParams: {
anchor: {
refreshModel: true
}
},
model: function(params) {
var aboutController = this.controllerFor('about');
aboutController.set('anchorLocation', params.anchor);
}
});
app/controllers/about.js
应用程序/控制器/about.js
import Ember from "ember";
export default Ember.Controller.extend({
queryParams: ['anchor'],
anchor: '',
showAnchor: function() {
var _this = this;
Ember.run.schedule('afterRender', function scrollToAnchor(){
var elem = Ember.$(_this.anchorLocation);
elem.get(0).scrollIntoView(true);
});
}.observes('anchorLocation'),
});
app/templates/footer.js
应用程序/模板/footer.js
<ul>
<li>
{{#link-to "about" (query-params anchor='#contact')}}Contact{{/link-to}}
</li>
<li>
{{#link-to "about" (query-params anchor='#support')}}Support{{/link-to}}
</li>
<li>
{{#link-to "about" (query-params anchor='#team')}}Team{{/link-to}}
</li>
</ul>
回答by Pascal
I got this working in Ember with the simple action approachfrom kroovy's answer.
我通过 kroovy 的回答中的简单操作方法在 Ember 中得到了这个。
Since Ember has changed its API I had to alter kroovys approach at little bit.
由于 Ember 改变了它的 API,我不得不稍微改变 kroovys 方法。
Two things have changed:
有两件事发生了变化:
- Events in an Ember.Route are deprecated and replaced by actions in Ember.Controller
- instead of transitionTo you have to use transitionToRoute
- Ember.Route 中的事件已弃用,取而代之的是 Ember.Controller 中的操作
- 而不是 transitionTo 你必须使用 transitionToRoute
Here is how I got it working in Ember Version 1.7.0
这是我在 Ember 版本 1.7.0 中工作的方式
Ember Handlebars-Template new.hbs
Ember把手-模板new.hbs
{{!-- Navigation --}}
<ul>
<li {{action 'goToLink' "new" "#part1"}}>Part 1</li>
<li {{action 'goToLink' "new" "#part2"}}>Part 2</li>
</ul>
{{!-- content --}}
<div id="part1" class="row">...</div>
<div id="part2" class="row">...</div>
Ember App.Controller NewController.js
Ember App.Controller NewController.js
App.NewController = Ember.ArrayController.extend({
actions: {
goToLink: function(item, anchor) {
console.log('NewController > goToLink');
var $elem = $(anchor);
var $scrollTo = $('body').scrollTop($elem.offset().top);
this.transitionToRoute(item.route).then( $scrollTo);
}
}
});
回答by SomeNameHere
If anyone's trying to solve this problem with Ember 3, I've got a solution. It makes use of the same queryParams approach as others have mentioned, but I couldn't get anything to work on the controller. The only approach that I found worked was to use the route + jQuery.ready function.
如果有人试图用 Ember 3 解决这个问题,我有一个解决方案。它使用与其他人提到的相同的 queryParams 方法,但我无法在控制器上进行任何操作。我发现唯一有效的方法是使用 route + jQuery.ready 函数。
// route/application.js
import Route from '@ember/routing/route';
import $ from 'jquery';
export default Route.extend({
queryParams: {
anchor: null
},
setupController: function(controller, context, params) {
let anchor = params.queryParams.anchor;
// On ready, find the anchor offset and go there
$().ready(function() {
let anchorOffset = $("#" + anchor).offset().top
window.scrollTo(0, anchorOffset);
});
}
});
Then in the template, use your queryParams as usual:
然后在模板中,像往常一样使用您的 queryParams:
{{#link-to "path.to.page" (query-params anchor="my-anchor")}}My Link{{/link-to}}
Only issue here is that it's reloading the page every time, but apart from that seems to work - hope it helps someone.
这里唯一的问题是它每次都重新加载页面,但除此之外似乎还可以 - 希望它对某人有所帮助。
回答by monty_lennie
My problem was that if I clicked on the destination link from another page, it would go to the destination but not scroll down to the correct portion of the page. After a few hours here was my fix:
我的问题是,如果我从另一个页面点击目标链接,它会转到目标但不会向下滚动到页面的正确部分。几个小时后,这是我的修复:
note: I'm using ember-cli
, and emblem
and ember 1.8
注意:我正在使用ember-cli
,emblem
和ember 1.8
link in my navigation bar
(in application.emblem
)
链接在我的navigation bar
(在application.emblem
)
li
a#concept-link click=jumpToConcept
| Le Concept
then if I'm already on page I just scroll up. If I'm not already on page then I go to that page with query params concept=true
那么如果我已经在页面上,我就向上滚动。如果我还没有在页面上,那么我会使用查询参数转到该页面concept=true
action
in application controller
action
在 application controller
scrollToConcept: function() {
Ember.$(document).ready(
Ember.$('html, body').animate({
scrollTop: Ember.$("#concept").offset().top
}, 750)
)
},
//allow clicking of link with specific id to go to that part of page
jumpToConcept : function(){
if (this.get('currentPath') === 'index') {
this.send('scrollToConcept');
} else {
this.transitionToRoute('index', { queryParams: {concept: true}});
}
}
in index controller
I then add the concept query params
在index controller
我然后添加concept query params
export default Ember.Controller.extend(
queryParams: ['concept'],
concept: null
}
I then add a scrollToConcept
event in index view
(the page I just went to) that listens for page loading and checks the concept queryParam
. If concept=true
I then scroll to the concept part of the page.
然后我scrollToConcept
在index view
(我刚刚访问的页面)中添加一个事件来监听页面加载并检查concept queryParam
. 如果concept=true
我然后滚动到页面的概念部分。
index view
index view
scrollToConcept: function() {
if (this.controller.get('concept') === 'true') {
Ember.$('html, body').animate({
scrollTop: Ember.$("#concept").offset().top
}, 750);
}
}.on('didInsertElement')
then for normal index links
, I add an action that sets concept=null
so that the concept query param
doesn't show up in the url.
然后对于 normal index links
,我添加了一个设置的操作,concept=null
以便concept query param
不会显示在 url 中。
link in nav bar
链接 nav bar
a click=goToIndex
h3 id={logoClass} Happy Dining
then in application controller
I go the the index route
, set the concept query param
to null (so it doesn't show up in the url) and scroll to the top (just incase it was lower on the page)
然后在application controller
我转到 ,将index route
设置concept query param
为空(因此它不会显示在 url 中)并滚动到顶部(以防它在页面上较低)
actions: {
goToIndex: function() {
this.transitionToRoute('index', { queryParams: {concept: null}});
Ember.$(window).scrollTop(0);
}
}
Hope that helps people in the future!!!
希望对以后的人有所帮助!!!