有人知道如何在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 Scroll库的详细信息:

Github - https://github.com/oblador/angular-scroll

凉亭:凉亭安装-保存角度-滚动

NPM install——保存angular-scroll

精简版-只有9kb

平滑滚动(动画滚动)-是的

滚动间谍-是的

文档-优秀

演示- http://oblador.github.io/angular-scroll/

希望这能有所帮助。

其他回答

在我的例子中,我注意到如果修改$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);
};

这是一个老帖子,但我花了很长时间研究各种解决方案,所以我想分享一个更简单的解决方案。只是添加target="_self"到<a>标签为我修复了它。该链接工作,并把我带到页面上的适当位置。

然而,Angular仍然在URL中注入了一些奇怪的#,所以在使用这个方法后,你可能会在使用返回按钮导航等方面遇到麻烦。

这是我使用一个指令的解决方案,它看起来更像angular,因为我们处理的是DOM:

这里的Plnkr

github

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

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

我使用$anchorScroll服务。为了抵消随散列改变而来的页面刷新,我取消了locationChangeStart事件。这对我来说很有效,因为我有一个连接到ng-switch的帮助页面,而刷新基本上会破坏应用程序。

轻松获得滚动功能。它还支持动画/平滑滚动作为附加功能。Angular Scroll库的详细信息:

Github - https://github.com/oblador/angular-scroll

凉亭:凉亭安装-保存角度-滚动

NPM install——保存angular-scroll

精简版-只有9kb

平滑滚动(动画滚动)-是的

滚动间谍-是的

文档-优秀

演示- http://oblador.github.io/angular-scroll/

希望这能有所帮助。

您正在寻找$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>