我有一个令人沮丧的早晨。
我有一个具有基本位置的应用,所以头部是<base href="/my/path/fruits/index.html" />
。我正在尝试通过函数nextPage()
设置分页。当我点击触发nextPage()
的链接时,我会使用$location.path('/page/:page')
。
预期行为:浏览器位置网址应更改为http://localhost/my/path/fruits/page/2
。
实际行为:浏览器网址(非常短暂地)更改为http://localhost/my/path/fruits/page/2
,然后还原为http://localhost/my/path/fruits/
。
注意:如果我没有使用基本位置,似乎不会发生此行为。但是,我需要使用基本位置,因为应用程序位于服务器的子/子/子目录中。
:如果我设置$locationProvider.html5Mode(false)
,则不会发生此行为。
我做错了吗?这是Angular中的错误吗?非常感谢任何帮助。
以下是相应的文件。
的index.html:
<!doctype html>
<html ng-app="fruits">
<head>
<base href="/my/path/fruits/index.html" />
<script src="angular.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-controller="MainCntl">
<div ng-view></div>
</div>
</body>
</html>
的script.js:
angular.module('fruits', [], function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'fruits.html',
controller: FruitCntl,
})
.when('/page/:page', {
templateUrl: 'fruits.html',
controller: FruitCntl,
})
.otherwise({redirectTo:'/'})
;
// configure html5
$locationProvider.html5Mode(true).hashPrefix('!');
}).filter('startFrom', function()
{
return function(input, start)
{
start = +start; //parse to int
if (input == undefined){
input = [];
}
return input.slice(start);
}
})
;
function MainCntl($scope,$location){
angular.extend($scope,{
current_page: 1,
per_page: 3,
fruits: [
{name: 'Apples', color: 'red'},
{name: 'Bananas', color: 'yellow'},
{name: 'Oranges', color: 'orange'},
{name: 'Grapes', color: 'purple'},
{name: 'Blueberries', color: 'blue'},
{name: 'Strawberries', color: 'red'},
{name: 'Raspberries', color: 'red'},
{name: 'Clementines', color: 'orange'},
{name: 'Pears', color: 'green'},
{name: 'Mangoes', color: 'orange'}
],
nextPage: function(){
this.current_page++;
$location.path('/page/'+this.current_page);
},
previousPage: function(){
this.current_page--;
$location.path('/page/'+this.current_page);
}
})
$scope.total_pages = Math.ceil($scope.fruits.length / $scope.per_page);
}
function FruitCntl($scope,$location,$routeParams){
if ($routeParams.page != undefined){
$scope.current_page = $routeParams.page;
}
}
fruits.html(视图)
Page: <a ng-click="previousPage()" ng-show="current_page > 1">Previous</a> {{current_page}} of {{total_pages}} <a ng-click="nextPage()" ng-show="current_page < total_pages">Next</a>
<div ng-repeat="fruit in fruits | startFrom:(current_page - 1)*per_page | limitTo:per_page">
{{fruit.name}} are {{fruit.color}}<br/>
</div>
答案 0 :(得分:9)
我遇到了同样的问题,并且在我的生活中无法弄清楚出了什么问题。 对我来说有用的是更改锚标签,该标签将ng-click事件附加到按钮标签上。从我可以收集的内容中,当没有给出href属性来阻止默认操作时,Angular会修改锚标记的行为,因此如果您在ng-click事件处理程序中手动更新位置,这可能会产生干扰。这只是我的猜测,所以希望有人能够更好地解释。
答案 1 :(得分:5)
您的浏览器回滚正在发生,因为网址更改发生了两次,当ng-click功能触发时,一次发生了标签的默认浏览器行为。
这就是为什么你在url / view中看到更新然后它又回到了原始状态。
它以这种方式发生,因为这是浏览器应该理解的。
按钮解决方案 如前所述,您可以触发按钮上的ng-单击,这是有效的,因为该按钮没有更新URL的有意义的href属性。您可以在按钮中添加href但不会执行任何操作。
标记: 而不是在ng-click中进行更新,避免使用函数并使href执行更改url的逻辑。这是一个更清洁的解决方案,因为您让浏览器执行更新URL的标记的默认行为。
我看到这样做的好处是任何人都可以一目了然地了解url shceme,因此代码更容易维护。
<a href="#/go/to/logic/5">Update to logic 5</a>
带有ng-click的标记: 如果您绝对需要以编程方式进行更改,那么您应该做的是避免标记的默认行为。
在jQuery中,您将绑定到click事件并执行event.preventDefault(),然后执行自定义逻辑。
由于框架所施加的逻辑分离,AngularJS方式略有不同,因此解决此问题的方法是创建一个指令来执行preventDefault。
IgnoreClick directive.js
angularModule.directive('ignoreClick', function() {
return {
restrict: 'A',
link: function(scope, element) {
element.bind('click', function(event) {
event.preventDefault();
});
}
}
});
用法示例
<a href=”http://stackoverflow.com/” ignore-click=”ignore-click” ng-click=”whatever()”>Don't Go</a>
答案 2 :(得分:0)
也许这不能直接回答你的问题,为什么它会以这种方式工作,或者这是一个错误,因为我无法轻易地重现它(我的意思是基本路径),但是我会尝试建议你一些解决方案
您应该尝试使用url params,例如?page = 4,而不是使用url更改来指示要与 reloadOnSearch:false param一起显示的页面,如下所示:
$routeProvider
.when('/', {
templateUrl: 'fruits.html',
controller: FruitCntl,
reloadOnSearch: false
})
.otherwise({redirectTo:'/'})
我认为在你的情况下只有一条路线就足够了。现在我们必须更改分页逻辑以使用$ location(而不是$ location.path)中的搜索功能:
$location.search('page', this.current_page);
这样,每次更改页面时,它都会在不创建新控制器的情况下更新页面。它还简化了路由逻辑。希望有所帮助!
注意:我必须删除 $ locationProvider.html5Mode(true).hashPrefix('!'); ,因为它在本地运行时会破坏网站。< / p>