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

sha*_*ker 8 angularjs

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

标准的工作锚链:

<a href="#foo">Link text</a>
... [page content]
<a id="foo"></a>
<h1>Headline</h1>
[more content]
Run Code Online (Sandbox Code Playgroud)

这很好.现在我在某处介绍一个模板部分:

<script type="text/ng-template" id="test-include.html">
  <p>This text is in a separate partial and inlcuded via ng-include.</p>
</script>
Run Code Online (Sandbox Code Playgroud)

通过以下方式调用:

<div ng-include="'test-include.html'"></div>
Run Code Online (Sandbox Code Playgroud)

部分包含正确,但锚链接不再起作用.单击"链接文本"现在将显示的URL更改为/#/foo而不是/#foo页面位置不会更改.

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

我不打算使用路由系统 - 我只是想在ng-include不弄乱浏览器行为的情况下使用它.这可能吗?

cod*_*mer 6

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

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

<a ng-click="scroll()">Link text</a>
Run Code Online (Sandbox Code Playgroud)

并在控制器中:

function MyCtrl($scope, $location, $anchorScroll) {
  $scope.scroll = function() {
    $location.hash('foo');
    $anchorScroll();
  };
};
Run Code Online (Sandbox Code Playgroud)

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

或者简单地使用双哈希:

<a href='##foo'>Link text</a>
Run Code Online (Sandbox Code Playgroud)

演示: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'));
    }
  };
});
Run Code Online (Sandbox Code Playgroud)

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


art*_*iak 2

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

路由系统是在单独的模块中定义的ngRoute,因此如果您没有自己注入它 - 我很确定您没有 - 它根本无法访问。

这里的问题有些不同。

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

最自然的调查候选者是$anchorScroll。的代码$anchorScroll看起来没有什么坏处,但是服务依赖$window,,$location$rootScope第616行$location说:

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

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

现在看这里 - 来自 BalusC 的答案

至于使用诸如 之类的命名锚点,通过标签,您基本上声明了与其相关的所有相对链接,包括命名锚点。所有相对链接都不再与当前请求 URI 相关(没有标签也会发生这种情况)。

如何缓解这个问题?

我今天没有太多时间,所以无法自己测试它,但我会尝试检查第一个选项是连接到“$locationChangeStart”事件,如果新的 url 类型#xxxxxx只是阻止默认行为并滚动$anchorScroll而是使用本机方法。

更新

我认为这段代码应该完成这项工作:

$scope.$on("$locationChangeStart", function (event, next, current) {

    var el, elId;

    if (next.indexOf("#")>-1) {
        elId = next.split("#")[1];
        el = document.getElementById(elId);
        if(el){
           // el.scrollIntoView(); do not think we need it
           window.location.hash = "#" + elId;
           event.preventDefault();
        }    
    }
});
Run Code Online (Sandbox Code Playgroud)