繁体   English   中英

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

[英]Remove hashchange event from Angular, or prevent Angular from rewriting anchor links

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

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

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

有可能:

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

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

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

$locationProvider.html5Mode(true)

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

我相信你想要$ anchorScroll 请参阅此相关答案: 如何在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演示$ anchorScroll

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

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

并将其添加到运行配置:

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

请参阅plunker演示滚动路由和$ anchorScroll

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

我做了一些改动,但我相信导致锚链接再次工作的那个是增加return; Angular来源中location.js第844行的声明:

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

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

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

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

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

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

例如:

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

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

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

看看这里

“有两件事需要做。

  1. 配置$ locationProvider
  2. 为相关链接设置基础

或者在这里

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

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

HTH

但为什么不使用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>

当用户点击此链接时

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

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

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

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

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

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

相关链接

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

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

服务器端

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

ngSource

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM