与NG-包括preserve传统锚行为传统、行为、NG、preserve

2023-09-13 02:59:49 作者:一席青城

我不是建立一个单页的应用程序,而是使用AngularJS的地方传统的网站。我已经打了以下问题(使用1.3.0-beta.6):

标准,工作锚链接:

 < A HREF =#富>链接文字< / A>... [网页内容]<一个ID =foo的>< / A>< H1>标题< / H1>[更多内容] 

这工作正常。现在我介绍一个模板部分地方:

 <脚本类型=文/ NG-模板ID =测试include.html>  < P>这文字是在一个单独的部分,并通过inlcuded NG-包括< / P>< / SCRIPT> 

这是通过调用:

 < D​​IV NG-包括=测试include.html'>< / DIV> 

部分适当地包括,但锚链接不再起作用。点击链接文本现在改变显示的网址以 /#/富,而不是 /#富和页面位置不会改变。

我的理解是,使用 NG-包括含蓄地告诉角度,我想使用的路由系统及覆盖浏览器的原生锚链接的行为。我见过的建议改变我的html锚链接#/#富来解决这个问题,但我不能这样做,因为其他原因。

我不打算使用的路由系统 - 我只是想用 NG-包括没有它与浏览器行为搞乱。这可能吗?

解决方案   

我的理解是,采用NG-包括隐含告诉角  我想使用的路由系统及覆盖浏览器的  本地锚链接的行为。我见过的建议来解决  这个改变我的html锚链接到#/#富,但我不能这样做  其他原因。

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

问题就在这里有些不同。

NG-包括取决于: $ HTTP $ templateCache $ anchorScroll $动画 $ SCE 。因此,请使用 NG-包括启动所有这些服务。

最自然的候选者,调查将 $ anchorScroll 。 $ anchorScroll 似乎并没有做任何伤害,但该服务依赖于 $窗口 $位置 $ rootScope $位置的行616说:

  baseHref = $ browser.baseHref()//如果基地[HREF]是不确定的,它默认为'' 

所以基本上基本href设置为,如果没有一套了。

现在看这里 - 从BalusC答案

  

至于使用命名锚一样,与标签  你基本上宣布所有相关链接相对于它,  包括命名锚。相对链接都不是相对于  当前请求的URI了(因为会发生不  标记)。

如何缓解这一问题?

我没有太多的时间在今天,所以无法测试它自己,但我会尝试检查作为第一个选项是挂钩到的$ locationChangeStart事件,如果新的URL是 #XXXXXX 键入只是prevent默认的行为和滚动与 $ anchorScroll 本地方法来代替。

更新

我觉得这$​​ C $ C应该做的工作:

  $范围。在$($ locationChangeStart功能(事件,接下来,电流){    VAR埃尔,ELID;    如果(next.indexOf(#)-1个){        ELID = next.split(#)[1];        EL =的document.getElementById(ELID);        如果(EL){           // el.scrollIntoView();不认为我们需要它           window.location.hash =#+ ELID;           。事件preventDefault();        }    }}); 

I am not building a single-page application, but rather a "traditional" site that uses AngularJS in places. I've hit the following problem (using 1.3.0-beta.6):

Standard, working anchor links:

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

That works fine. Now I introduce a template partial somewhere:

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

which is invoked via:

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

The partial is included properly, but the anchor link no longer works. Clicking on "Link text" now changes the displayed URL to /#/foo rather than /#foo and the page position does not change.

My understanding is that using ng-include implicitly tells Angular that I want to use the routes system and overrides the browser's native anchor link behavior. I've seen recommendations to work around this by changing my html anchor links to #/#foo, but I can't do that for other reasons.

I don't intend to use the routes system - I just want to use ng-include without it messing with browser behavior. Is this possible?

解决方案

My understanding is that using ng-include implicitly tells Angular that I want to use the routes system and overrides the browser's native anchor link behavior. I've seen recommendations to work around this by changing my html anchor links to #/#foo, but I can't do that for other reasons.

Routing system is defined in a separate module ngRoute, so if you did not injected it on your own - and I am pretty sure you did not - it is not accessible at all.

The issue is somehow different here.

ng-include depends on: $http, $templateCache, $anchorScroll, $animate, $sce. So make use of ng-include initiate all these services.

The most natural candidate to investigate would be $anchorScroll. The code of $anchorScroll does not seem to do any harm, but the service depends on $window, $location, $rootScope. The line 616 of $location says:

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

So basically the base href is set to '', if it was no set before.

Now look HERE - from BalusC answer :

As to using named anchors like , with the tag you're basically declaring all relative links relative to it, including named anchors. None of the relative links are relative to the current request URI anymore (as would happen without the tag).

How to mitigate the issue?

I do not have much time today, so cannot test it myself, but what I would try to check as the first option is to hook up to '$locationChangeStart' event and if the new url is of #xxxxxx type just prevent the default behaviour and scroll with $anchorScroll native methods instead.

Update

I think this code should do the work:

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