使用ng-include保留传统锚定行为

时间:2014-04-25 18:00:20

标签: angularjs

我不是在构建一个单页应用程序,而是一个传统的"在某些地方使用AngularJS的网站。我遇到了以下问题(使用1.3.0-beta.6):

标准的工作锚链接:

<a href="#foo">Link text</a>
... [page content]
<a id="foo"></a>
<h1>Headline</h1>
[more content]

工作正常。现在我在某处介绍一个模板部分:

<script type="text/ng-template" id="test-include.html">
  <p>This text is in a separate partial and inlcuded via ng-include.</p>
</script>

通过以下方式调用:

<div ng-include="'test-include.html'"></div>

正确包含部分,但锚链接不再有效。点击&#34;链接文字&#34;现在将显示的网址更改为/#/foo而不是/#foo,页面位置不会更改。

我的理解是使用ng-include隐式告诉Angular我想使用routes系统并覆盖浏览器的原生锚链接行为。我已经看到了通过将我的html锚链接更改为#/#foo来解决此问题的建议,但出于其他原因我无法做到这一点。

我不打算使用路由系统 - 我只想使用ng-include而不会弄乱浏览器行为。这可能吗?

5 个答案:

答案 0 :(得分:6)

原因是angular会覆盖包含<a>的标准HTML标记的行为。我不确定这个改变何时发生,因为角度v1.0.1可以正常工作。

您应该使用ngClick替换href属性:

<a ng-click="scroll()">Link text</a>

在控制器中:

function MyCtrl($scope, $location, $anchorScroll) {
  $scope.scroll = function() {
    $location.hash('foo');
    $anchorScroll();
  };
};

演示:http://jsfiddle.net/HB7LU/3261/show/

或者只是使用双重哈希:

<a href='##foo'>Link text</a>

演示:http://jsfiddle.net/HB7LU/3262/show/

更新:我不知道您不想在HREF中进行任何修改。但是,您仍然可以通过将现有的a指令覆盖为:

来实现所需的结果
myApp.directive('a', function() {
  return {
    restrict: 'E', 
    link: function(scope, element) {
        element.attr('href', '#' + element.attr('href'));
    }
  };
});

演示:http://jsfiddle.net/HB7LU/3263/

答案 1 :(得分:2)

  

我的理解是使用ng-include隐式告诉Angular   我想使用路由系统并覆盖浏览器   本机锚链接行为。我已经看到了可以解决的建议   这通过将我的html锚链接更改为#/#foo,但我无法做到这一点   出于其他原因。

路由系统是在一个单独的模块ngRoute中定义的,所以如果你没有自己注入它 - 而且我很确定你没有 - 它完全无法访问。

这个问题在某种程度上有所不同。

ng-include取决于:$http$templateCache$anchorScroll$animate$sce。因此,请使用ng-include启动所有这些服务。

最自然的调查对象是$anchorScroll$anchorScroll的代码似乎没有任何损害,但服务取决于$window$location$rootScope$location的第616行说:

 baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''

基本上,如果之前没有设置,则基本href设置为''

现在看HERE - from BalusC answer

  

关于使用带有标记的命名锚点   你基本上宣布了相对于它的所有相关链接,   包括命名锚点。没有相关链接是相对的   当前的请求URI已经存在(如果没有,那就会发生   标记)。

如何缓解这个问题?

我今天没有太多时间,所以无法自己测试,但我会尝试检查第一个选项是连接到'$locationChangeStart'事件,如果新网址是{{1} } type只是阻止默认行为,而是用#xxxxxx 本机方法滚动

更新

我认为这段代码可以完成这项工作:

$anchorScroll

答案 2 :(得分:2)

这是最好的解决方案,适用于Angular的最新版本:

Turn off URL manipulation in AngularJS

答案 3 :(得分:2)

派对很晚但我发现添加一个简单的目标=“_ self”修复了它。

<a href="#anchor" target="_self">Link</a>

答案 4 :(得分:1)

您可以将应用程序隔离到您要执行ng-include的位置,而不是将角度应用程序应用于整个页面。这将允许应用程序范围之外的链接保留其正常功能,同时允许应用程序内的链接按需处理。

见这个plunkr:

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

plunkr在应用程序外部显示正常运行的链接,并在应用程序中显示使用覆盖a指令处理的链接以恢复正常功能。启用HTML5模式以保留“标准”网址(而非“hashbang”[没有爆炸!]网址)。

你可以同样在应用程序中运行整个页面,但我认为在任何情况下都值得演示如何将角度分离到页面的某些部分。