从Angular中删除hashchange事件,或阻止Angular重写锚链接

时间:2016-06-20 16:33:00

标签: javascript angularjs anchor angular-routing

我们有一个使用Angular的项目,但仅限于它的UI绑定/ AJAX方面,不适用于任何类型的路由或SPA功能。

我们希望能够在我们选择的CMS中编写的文章中使用锚链接(#section-2),以及使用其他页面的锚链接(/my-page#section-C),但Angular重写这些是#/section-2,它打破了CMS设置的锚链接。

无法扩充CMS以修改锚链接的处理方式。

是否可以:

  1. 从Angular中删除hashchange事件绑定?我看到这个事件附加在源文件src/ng/browser.js中,在那里它处理一些路由和链接重写,但是它在一个闭包内部,因此无法直接访问它(我们从CDN链接到Angular)所以不可能修改Angular源,而且我们不想维护我们自己的“自定义”Angular源。

  2. 设置选项或调用配置方法,最终会禁用Angular的整个路由方面并阻止它重写任何类型的链接? (或者,有没有办法不包括Angular的这部分,但仍保留控制器/ UI绑定/ AJAX功能?)

  3. 请注意,我已经尝试过这个:

    $locationProvider.html5Mode(true)
    

    然而,它会使网站上的所有其他链接无法运行,因为所有链接都通过Angular进行处理。因此,如果我链接到主页(<a href="/">Home</a>)并点击html5mode上的链接,则链接不执行任何操作。

6 个答案:

答案 0 :(得分:3)

我相信你想要$anchorScroll。请参阅此相关答案:How to handle anchor hash linking in AngularJS

这是一个如何工作的例子。哈希只被视为id的一部分:

app.controller('TestCtrl', function($location, $anchorScroll) {
   var vm = this;
   vm.scrollTo = function(id) {
      $location.hash(id);
      $anchorScroll();
   }
});

<a ng-click="vm.scrollTo('#foo')">Foo</a>

<div id="#foo">Here you are</div>

请参阅plunker demonstrating $anchorScroll

通过路由,您可以将链接更改为:

<a href="#/test##foo">Test/Foo</a>

并将其添加到运行配置中:

 $rootScope.$on('$routeChangeSuccess', function(newRoute, oldRoute) {
    if($location.hash()) {
        $anchorScroll();  
    }
 });

请参阅plunker demonstrating scrolling with routing and $anchorScroll

答案 1 :(得分:2)

作为一种解决方法(当然不是最佳实践),我最终修改了Angular源以删除URL重写。

我做了一些更改,但我相信导致锚定链接再次起作用的是在Angular源代码中return;的第844行添加location.js语句:

https://github.com/angular/angular.js/blob/master/src/ng/location.js#L844

这会使大部分网址重写功能出现短路。

我还完全移除了browser.js的第262-264行,删除了hashchange事件上的Angular钩子:

https://github.com/angular/angular.js/blob/master/src/ng/browser.js#L262-264

这似乎并没有影响Angular的任何绑定功能,但它确实导致锚链接重新开始工作。

答案 2 :(得分:1)

Angular的$locationProvider.html5Mode function with it's rewriteLinks设置正是您所需要的。它将角度置于一种模式,其中$ location仍可用于读取和写入浏览器的URL,但它不会试图劫持链接点击并触发angular的SPA路由。

例如:

  $locationProvider.html5Mode({
      enabled: true,
      requireBase: false,
      rewriteLinks: false 
  });

答案 3 :(得分:0)

设置$ locationProvider.html5Mode(true)后,您是否还在文档的<base>中设置了<head>

<html>
  <head>
    <base href="/">
  </head>
</html>

看看here

&#34;有两件事需要做。

  1. 配置$ locationProvider
  2. 设置相关链接的基础
  3. here

答案 4 :(得分:0)

使用带有wordpress的角度时遇到了类似的问题,发现了一个非常简单的修复方法。您所要做的就是删除控制器中的所有$ location注入。当你注入$ location服务(无论你是否使用它)时,它会劫持#行为。

这意味着您必须遍历所有控制器,指令等,并确保$ location服务不会被注入任何地方。

HTH

答案 5 :(得分:-2)

但为什么不使用ng-route?它会完全解决你的问题。使用Ng路线,您可以实现以下目标(这就是您想要的)。

<a href="http://www.example.com/base/#section-A"> Section A</a>

<a href="http://www.example.com/base/my-page#section-C">Another page</a>

<a href="/other-base/another?search">external</a>

这是app.js片段

app.config(function($locationProvider) {
  $locationProvider.html5Mode(true).hashPrefix('!');
})

Html链接重写

使用HTML5历史记录API模式时,您不需要特殊的hashbang链接。您所要做的就是指定常规的URL链接,例如:<a href="/some?foo=bar">link</a>

当用户点击此链接时,

在旧版浏览器中,网址更改为/index.html#!/some?foo=bar

在现代浏览器中,网址更改为/some?foo=bar

如下所示,链接不会被重写;相反,浏览器将执行整页重新加载到原始链接。

包含目标元素的链接 示例:<a href="/ext/link?a=b" target="_self">link</a>

转到其他域的绝对链接 示例:<a href="http://angularjs.org/">link</a>

以&#39; /&#39;开头的链接导致不同的基本路径 示例:<a href="/not-my-base/link">link</a>

相对链接

请务必检查所有相关链接,图像,脚本等.Angular要求您在主html文件(<base href="/my-base/index.html">)的头部指定url base,除非在html5Mode中将html5Mode.requireBase设置为false传递给$ locationProvider.html5Mode()的定义对象。这样,即使文档的初始URL不同,相对URL也将始终解析为此基本URL。

有一个例外:仅包含哈希片段(例如<a href="#target">)的链接只会更改$ location.hash(),否则不会修改URL。这对于滚动到同一页面上的锚点非常有用,而无需知道用户当前在哪个页面上。

服务器端

使用此模式需要在服务器端重写URL,基本上您必须重写所有指向应用程序入口点的链接(例如index.html)。在这种情况下,需要标记也很重要,因为它允许Angular区分作为应用程序库的url部分和应用程序应该处理的路径。

ngSource