有人知道如何在AngularJS中很好地处理锚散列链接吗?

对于一个简单的faq页面,我有以下标记

<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”的路由,并在相应的控制器中检查$routeParams。然后使用jQuery向下滚动到它。

但是AngularJS又把我搞砸了,反正就是滚动到页面顶部。

有人在过去做过类似的事情并且知道一个好的解决方法吗?

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


当前回答

我试图让我的Angular应用在加载时滚动到一个锚点,却遇到了$routeProvider的URL重写规则。

经过长时间的试验,我确定了这一点:

注册一个文档。的.run()部分中的Onload事件处理程序 Angular的app模块。 在处理程序中找出原来的 锚标签应该是通过做一些字符串操作。 覆盖的位置。哈希与剥离锚标记(其中 导致$routeProvider立即再次覆盖它 “# /”规则。但这没关系,因为Angular现在与 URL调用$anchorScroll()中发生了什么。

[], angular.module (bla)。}]) .run(函数(位置,anchorScroll美元){ $(文档)时函数(){ 如果位置。location.hash.length>=1) { Var path = location.hash; var potentialAnchor = path.substring(path.lastIndexOf("/")+1); if($(“#”+ potentialAnchor)。长度> 0){//确保该标签在doc中存在。 的位置。hash = potentialAnchor; 美元anchorScroll (); } } });

其他回答

见https://code.angularjs.org/1.4.10/docs/api/ngRoute/provider/ routeProvider美元

[reloadOnSearch=true] - {boolean=} -仅当$location.search()或$location.hash()发生变化时重新加载路由。

对我来说,把这个设置为false就可以了。

我可以这样做:

<li>
<a href="#/#about">About</a>
</li>

在路径更改时,它将滚动到页面顶部。

 $scope.$on('$routeChangeSuccess', function () {
      window.scrollTo(0, 0);
  });

把这段代码放在控制器上。

您正在寻找$anchorScroll()。

这是(蹩脚的)文档。

这是来源。

基本上你只需要注入它并在控制器中调用它,它就会滚动到$location。hash()中id为的任何元素

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>

这里有一个活塞来演示

EDIT:用于路由

像往常一样设置angular路由,然后添加以下代码。

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>

这里是一种肮脏的工作方法,通过创建自定义指令,将滚动到指定的元素(硬编码的“faq”)

app.directive('h3', function($routeParams) {
  return {
    restrict: 'E',
    link: function(scope, element, attrs){        
        if ('faq'+$routeParams.v == attrs.id) {
          setTimeout(function() {
             window.scrollTo(0, element[0].offsetTop);
          },1);        
        }
    }
  };
});

http://plnkr.co/edit/Po37JFeP5IsNoz5ZycFs?p=preview