2012-07-20 121 views
52

我有一个启用了HTML5模式的工作Angular.js应用程序。angular.js链接行为 - 禁用特定URL的深层链接

$location.Html5mode(true).hashbang("!"); 

我想达到的目标是得到一些网址或<a>标签做正常的浏览行为,而不是使用HTML5历史API改变URL地址栏和采用了棱角分明的控制器处理它的。

我有这个链接:

<a href='/auth/facebook'>Sign in with Facebook</a> 
<a href='/auth/twitter'>Sign in with Twitter</a> 
<a href='/auth/...'>Sign in with ...</a> 

而且我希望浏览器将用户重定向到/auth/...这样用户将被随后重定向到验证服务。

有什么办法可以做到这一点?

回答

117

添加在角1.0.1 target="_self"作品:

<a target="_self" href='/auth/facebook'>Sign in with Facebook</a> 

此功能是记录(https://docs.angularjs.org/guide/$location - 搜索 '_self')

如果你很好奇,看看角源代码(5365行@ v1.0.1)。仅当!elm.attr('target')为真时才会发生点击劫持。

+0

使用角1.2.16和可能与当前的主人https://github.com/angular/angular.js/blob/master/src/ng/location.js#L687 – 2014-06-22 17:04:03

+0

很好很干净! – 2014-07-16 02:27:06

+1

不得不使用它来启用转换时间段,同时将导轨路线转换为角度路线 – Mikey 2014-10-03 11:18:08

1

我已经用角度碰到了几次相同的问题,虽然我已经想出了两个功能解决方案,但都觉得像hacks而不是非常“有棱角”。

哈克#1:

绑定window.location刷新链接的click事件。

<a 
    href=/external/link.html 
    onclick="window.location = 'http://example.com/external/link.html';" 
> 

这种方法的缺点和问题相当明显。

哈克#2

安装角$route s表示执行$window.location变化。

// Route 
.when('/external', { 
    templateUrl: 'path/to/dummy/template', 
    controller: 'external' 
}) 

// Controller 
.controller('external', ['$window', function ($window) { 
    $window.location = 'http://www.google.com'; 
}]) 

我想,你可以使用$routeParams或查询字符串有一个控制器处理所有的“外部”链接扩展此。

正如我所说,这些解决方案都不是非常令人满意,但如果您必须在短期内实现这一目标,那么它们可能会有所帮助。

在附注上,我非常希望看到支持这种功能的Angular支持rel=external,就像jQueryMobile使用它来禁用Ajax页面加载一样。

+0

我想看看有'rel = external'工作压力太大。在此之前,我将使用** hack#2 **。我会尽快将你的答案标记为接受,但我想再等一会儿,看看是否有人以更为有效的方式解决了这个问题。谢谢! – 2012-07-20 15:48:27

+0

我有类似的想法,特别是使用'$ window.location'在'html5mode = true'中强制页面刷新 - 这在Webkit浏览器中无法正常工作;绝对使用'target = _self'。 – jlmakes 2013-05-03 13:47:09

0

在你的路由尝试:

$routeProvider.otherwise({})

+0

不起作用。只有当我使用诺亚答案中的外部控制器。 – 2012-07-21 14:14:10

16

这是关闭所有深层链接在一起的代码。它禁用rootElement中的单击事件处理程序。

angular.module('myApp', []) 
    .run(['$location', '$rootElement', function ($location, $rootElement) { 
     $rootElement.off('click'); 
}]); 
+0

这是混合MVC/Angular站点的一个很好的解决方案,其中一些链接是由Angular路由配置拦截的mini-SPA,而其他链接则是针对常规MVC页面请求。在我的情况下,正常的链接一直工作,直到角控制器被加载(当使用SPA时),此时常规的MVC链接被劫持并且没有产生任何响应。所以upvoted。 – Sean 2014-06-04 15:31:20

+0

无论你把'$ location'放在你身上,你都需要这样做:例如'.controller('fooController',function($ location){})''你需要删除类似'.controller('fooController',function($ element,$ location){$ element.off('click ');})'。 – tester 2014-08-06 01:01:25

+1

谢谢,我在页面上应用过滤器时使用pushstate来设置url。有了这个,我可以使用'$ location.search()',并且仍然有我的''标签正常工作。 (无需在每个地方都应用'target =“_ self”) – tomvo 2014-08-06 13:35:16

1

若要关闭聂的回答,如果你有很多的链接,并且不希望目标添加到他们每个人,你可以用一个指令:

Module.directive('a', function() { 
    return { 
     restrict: 'E', 
     link: function(scope, element, attrs) { 
      element.attr("target", "_self"); 
     } 
    }; 
}); 
0

为了增加蜻蜓的回答,我发现限制target =“_ self”属性的最佳做法是从不将ng-app属性放在body标签上。通过这样做,你告诉角度,一切内的身体标签是角应用程序的一部分。

如果你在一个不应受角度影响的静态包装中工作,将你的ng-app属性放在一个div上(或其他元素),只包围你的角度应用将要工作的位置。你只需要在将成为ng-app元素的子元素的链接上放置target ='_ self'属性。

<body> 
    ... top markup ... 
    <div ng-app="myApp"> 
     <div ng-view></div> 
    </div> 
    ... bottom markup ... 
</body> 
17

到Fran6co的还有另外一种方法来禁用在$ locationProvider的 'rewriteLinks' 选项:

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

这将完成同样的事情与调用$ rootElement.off( '点击') ,但不会干扰处理应用根元素上的点击事件的其他JavaScript。

docsrelevant source

+2

再加上所有人的标记 – sidonaldson 2015-03-02 10:05:01

+0

这对我不起作用,但@ Fran6co的[解决方案](http://stackoverflow.com/a/11785196/295686)差不多(见我的评论)。我在加载应用程序的页面上运行它,但没有控制器以锚标记所在的树为目标。 – mlhDev 2015-09-15 21:01:28

+1

对此答案+1。直到我在$ locationProvider上启用了html5Mode,问题才出现在第一位。 – 2016-01-27 16:04:31