如何处理AngularJS中的锚点哈希链接

2022-08-29 23:53:30

你们中有人知道如何在AngularJS中很好地处理锚点哈希链接吗?

我有一个简单的常见问题解答页面的以下标记

<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>

当点击上述任何链接时,AngularJS会拦截并将我路由到一个完全不同的页面(在我的情况下,是一个404页面,因为没有与链接匹配的路由。

我的第一个想法是创建一个匹配的路由“/faq/:chapter”,并在相应的控制器中检查匹配的元素,然后使用jQuery向下滚动到它。$routeParams.chapter

但是,AngularJS再次对我大发雷霆,无论如何都会滚动到页面顶部。

那么,这里是否有人在过去做过类似的事情,并且知道一个好的解决方案吗?

编辑:切换到html5Mode应该可以解决我的问题,但我们无论如何都必须支持IE8 +,所以我担心这不是一个被接受的解决方案:/


答案 1

您正在寻找$anchorScroll()

这是(蹩脚的)文档。

这是来源。

基本上,您只需注入它并在控制器中调用它,它就会将您滚动到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>

这是一个要演示的plunker

编辑:将其与路由一起使用

像往常一样设置角度路由,然后只需添加以下代码即可。

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();  
  });
});

并且您的链接将如下所示:

<a href="#/test?scrollTo=foo">Test/Foo</a>

这是一个Plunker演示滚动路由和$anchorScroll

甚至更简单:

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();  
  });
});

并且您的链接将如下所示:

<a href="#/test#foo">Test/Foo</a>

答案 2

在我的情况下,我注意到如果我修改.以下技巧奏效了。.$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);
};