我们有一个使用Angular的项目,但仅限于它的UI绑定/ AJAX方面,不适用于任何类型的路由或SPA功能。
我们希望能够在我们选择的CMS中编写的文章中使用锚链接(#section-2
),以及使用其他页面的锚链接(/my-page#section-C
),但Angular重写这些是#/section-2
,它打破了CMS设置的锚链接。
无法扩充CMS以修改锚链接的处理方式。
是否可以:
从Angular中删除hashchange
事件绑定?我看到这个事件附加在源文件src/ng/browser.js
中,在那里它处理一些路由和链接重写,但是它在一个闭包内部,因此无法直接访问它(我们从CDN链接到Angular)所以不可能修改Angular源,而且我们不想维护我们自己的“自定义”Angular源。
设置选项或调用配置方法,最终会禁用Angular的整个路由方面并阻止它重写任何类型的链接? (或者,有没有办法不包括Angular的这部分,但仍保留控制器/ UI绑定/ AJAX功能?)
请注意,我已经尝试过这个:
$locationProvider.html5Mode(true)
然而,它会使网站上的所有其他链接无法运行,因为所有链接都通过Angular进行处理。因此,如果我链接到主页(<a href="/">Home</a>
)并点击html5mode
上的链接,则链接不执行任何操作。
答案 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;有两件事需要做。
或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('!');
})
使用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部分和应用程序应该处理的路径。