Javascript 如何处理 AngularJS 中的锚点哈希链接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14712223/
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
How to handle anchor hash linking in AngularJS
提问by Rasmus
Do any of you know how to nicely handle anchor hash linking in AngularJS?
你们中有人知道如何在AngularJS 中很好地处理锚点哈希链接吗?
I have the following markup for a simple FAQ-page
我有一个简单的常见问题解答页面的以下标记
<a href="#faq-1">Question 1</a>
<a href="#faq-2">Question 2</a>
<a href="#faq-3">Question 3</a>
<h3 id="faq-1">Question 1</h3>
<h3 id="faq-2">Question 2</h3>
<h3 id="fa1-3">Question 3</h3>
When clicking on any of the above links AngularJS intercepts and routes me to a completely different page (in my case, a 404-page as there are no routes matching the links.)
当单击上述任何链接时,AngularJS 会拦截并将我路由到一个完全不同的页面(在我的情况下,是一个 404 页面,因为没有与链接匹配的路由。)
My first thought was to create a route matching "/faq/:chapter" and in the corresponding controller check $routeParams.chapterafter a matching element and then use jQuery to scroll down to it.
我的第一个想法是创建一个匹配“ /faq/:chapter”的路由,并在相应的控制器中检查$routeParams.chapter匹配的元素,然后使用 jQuery 向下滚动到它。
But then AngularJS shits on me again and just scrolls to the top of the page anyway.
但随后 AngularJS 又对我大发雷霆,无论如何只是滚动到页面顶部。
So, anyone here done anything similar in the past and knows a good solution to it?
那么,这里有人过去做过类似的事情并且知道一个好的解决方案吗?
Edit: Switching to html5Mode should solve my problems but we kinda have to support IE8+ anyway so I fear it's not an accepted solution :/
编辑:切换到 html5Mode 应该可以解决我的问题,但无论如何我们都必须支持 IE8+,所以我担心这不是一个可接受的解决方案:/
回答by Ben Lesh
You're looking for $anchorScroll().
您正在寻找$anchorScroll().
Here's the (crappy) documentation.
Basically you just inject it and call it in your controller, and it will scroll you to any element with the id found in $location.hash()
基本上,您只需注入它并在您的控制器中调用它,它就会将您滚动到具有 id 的任何元素 $location.hash()
app.controller('TestCtrl', function($scope, $location, $anchorScroll) {
$scope.scrollTo = function(id) {
$location.hash(id);
$anchorScroll();
}
});
<a ng-click="scrollTo('foo')">Foo</a>
<div id="foo">Here you are</div>
Here is a plunker to demonstrate
EDIT: to use this with routing
编辑:将其与路由一起使用
Set up your angular routing as usual, then just add the following code.
像往常一样设置您的角度路由,然后只需添加以下代码。
app.run(function($rootScope, $location, $anchorScroll, $routeParams) {
//when the route is changed scroll to the proper element.
$rootScope.$on('$routeChangeSuccess', function(newRoute, oldRoute) {
$location.hash($routeParams.scrollTo);
$anchorScroll();
});
});
and your link would look like this:
你的链接看起来像这样:
<a href="#/test?scrollTo=foo">Test/Foo</a>
Here is a Plunker demonstrating scrolling with routing and $anchorScroll
这是一个展示使用路由和 $anchorScroll 滚动的Plunker
And even simpler:
甚至更简单:
app.run(function($rootScope, $location, $anchorScroll) {
//when the route is changed scroll to the proper element.
$rootScope.$on('$routeChangeSuccess', function(newRoute, oldRoute) {
if($location.hash()) $anchorScroll();
});
});
and your link would look like this:
你的链接看起来像这样:
<a href="#/test#foo">Test/Foo</a>
回答by slugslog
In my case, I noticed that the routing logic was kicking in if I modified the $location.hash(). The following trick worked..
就我而言,我注意到如果我修改了$location.hash(). 以下技巧奏效了..
$scope.scrollTo = function(id) {
var old = $location.hash();
$location.hash(id);
$anchorScroll();
//reset to old to keep any additional routing logic from kicking in
$location.hash(old);
};
回答by Mauricio Gracia Gutierrez
There is no need to change any routing or anything else just need to use target="_self"when creating the links
target="_self"创建链接时无需更改任何路由或任何其他只需要使用的东西
Example:
例子:
<a href="#faq-1" target="_self">Question 1</a>
<a href="#faq-2" target="_self">Question 2</a>
<a href="#faq-3" target="_self">Question 3</a>
And use the idattribute in your htmlelements like this:
并id在您的html元素中使用该属性,如下所示:
<h3 id="faq-1">Question 1</h3>
<h3 id="faq-2">Question 2</h3>
<h3 id="faq-3">Question 3</h3>
There is no need to use ## as pointed/mentioned in comments ;-)
没有必要使用 ## 作为评论中指出/提到的 ;-)
回答by lincolnge
<a href="##faq-1">Question 1</a>
<a href="##faq-2">Question 2</a>
<a href="##faq-3">Question 3</a>
<h3 id="faq-1">Question 1</h3>
<h3 id="faq-2">Question 2</h3>
<h3 id="faq-3">Question 3</h3>
回答by cab1113
If you always know the route, you can simply append the anchor like this:
如果你总是知道路线,你可以像这样简单地附加锚点:
href="#/route#anchorID
where routeis the current angular route and anchorIDmatches an <a id="anchorID">somewhere on the page
route当前的角度路线在哪里并anchorID匹配<a id="anchorID">页面上的某个地方
回答by Rebecca
$anchorScrollworks for this, but there's a much better way to use it in more recent versions of Angular.
$anchorScroll对此有效,但有一种更好的方法可以在较新版本的 Angular 中使用它。
Now, $anchorScrollaccepts the hash as an optional argument, so you don't have to change $location.hashat all. (documentation)
现在,$anchorScroll接受散列作为可选参数,因此您根本不必更改$location.hash。(文档)
This is the best solution because it doesn't affect the route at all. I couldn't get any of the other solutions to work because I'm using ngRoute and the route would reload as soon as I set $location.hash(id), before $anchorScrollcould do its magic.
这是最好的解决方案,因为它根本不影响路线。我无法让任何其他解决方案工作,因为我正在使用 ngRoute 并且路线会在我设置后立即重新加载$location.hash(id),然后$anchorScroll才能发挥其魔力。
Here is how to use it... first, in the directive or controller:
这是如何使用它......首先,在指令或控制器中:
$scope.scrollTo = function (id) {
$anchorScroll(id);
}
and then in the view:
然后在视图中:
<a href="" ng-click="scrollTo(id)">Text</a>
Also, if you need to account for a fixed navbar (or other UI), you can set the offset for $anchorScroll like this (in the main module's run function):
此外,如果您需要考虑固定的导航栏(或其他 UI),您可以像这样设置 $anchorScroll 的偏移量(在主模块的运行函数中):
.run(function ($anchorScroll) {
//this will make anchorScroll scroll to the div minus 50px
$anchorScroll.yOffset = 50;
});
回答by KhalilRavanna
This was my solution using a directive which seems more Angular-y because we're dealing with the DOM:
这是我使用的指令的解决方案,它看起来更像 Angular-y,因为我们正在处理 DOM:
CODE
代码
angular.module('app', [])
.directive('scrollTo', function ($location, $anchorScroll) {
return function(scope, element, attrs) {
element.bind('click', function(event) {
event.stopPropagation();
var off = scope.$on('$locationChangeStart', function(ev) {
off();
ev.preventDefault();
});
var location = attrs.scrollTo;
$location.hash(location);
$anchorScroll();
});
};
});
HTML
HTML
<ul>
<li><a href="" scroll-to="section1">Section 1</a></li>
<li><a href="" scroll-to="section2">Section 2</a></li>
</ul>
<h1 id="section1">Hi, I'm section 1</h1>
<p>
Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering animata corpora quaeritis.
Summus brains sit??, morbo vel maleficia? De apocalypsi gorger omero undead survivor dictum mauris.
Hi mindless mortuis soulless creaturas, imo evil stalking monstra adventus resi dentevil vultus comedat cerebella viventium.
Nescio brains an Undead zombies. Sicut malus putrid voodoo horror. Nigh tofth eliv ingdead.
</p>
<h1 id="section2">I'm totally section 2</h1>
<p>
Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering animata corpora quaeritis.
Summus brains sit??, morbo vel maleficia? De apocalypsi gorger omero undead survivor dictum mauris.
Hi mindless mortuis soulless creaturas, imo evil stalking monstra adventus resi dentevil vultus comedat cerebella viventium.
Nescio brains an Undead zombies. Sicut malus putrid voodoo horror. Nigh tofth eliv ingdead.
</p>
I used the $anchorScroll service. To counteract the page-refresh that goes along with the hash changing I went ahead and cancelled the locationChangeStart event. This worked for me because I had a help page hooked up to an ng-switch and the refreshes would esentially break the app.
我使用了 $anchorScroll 服务。为了抵消随着散列更改而发生的页面刷新,我继续并取消了 locationChangeStart 事件。这对我有用,因为我有一个连接到 ng-switch 的帮助页面,刷新基本上会破坏应用程序。
回答by Maxim Grach
Try to set a hash prefix for angular routes $locationProvider.hashPrefix('!')
尝试为角度路由设置哈希前缀 $locationProvider.hashPrefix('!')
Full example:
完整示例:
angular.module('app', [])
.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider){
$routeProvider.when( ... );
$locationProvider.hashPrefix('!');
}
])
回答by nicksanta
I got around this in the route logic for my app.
我在我的应用程序的路由逻辑中解决了这个问题。
function config($routeProvider) {
$routeProvider
.when('/', {
templateUrl: '/partials/search.html',
controller: 'ctrlMain'
})
.otherwise({
// Angular interferes with anchor links, so this function preserves the
// requested hash while still invoking the default route.
redirectTo: function() {
// Strips the leading '#/' from the current hash value.
var hash = '#' + window.location.hash.replace(/^#\//g, '');
window.location.hash = hash;
return '/' + hash;
}
});
}
回答by Benjamin
This is an old post, but I spent a long time researching various solutions so I wanted to share one more simple one. Just adding target="_self"to the <a>tag fixed it for me. The link works and takes me to the proper location on the page.
这是一篇旧帖子,但我花了很长时间研究各种解决方案,所以我想分享一个更简单的解决方案。只需添加target="_self"到<a>标签即可为我修复它。该链接有效并将我带到页面上的正确位置。
However, Angular still injects some weirdness with the # in the URL so you may run into trouble using the back button for navigation and such after using this method.
但是,Angular 仍然在 URL 中注入了一些奇怪的 #,因此在使用此方法后,您可能会遇到使用后退按钮进行导航等问题。

