【问题标题】:AngularJS location.path() changes URL briefly, then revertsAngularJS location.path() 短暂更改 URL,然后恢复
【发布时间】:2012-11-11 02:17:41
【问题描述】:

我有一个令人沮丧的早晨。

我有一个具有基本位置的应用程序,所以头部是<base href="/my/path/fruits/index.html" />。我正在尝试通过函数nextPage() 设置分页。当我点击触发nextPage() 的链接时,我使用$location.path('/page/:page')

预期行为:浏览器位置 url 应更改为 http://localhost/my/path/fruits/page/2

实际行为: 浏览器 URL 更改(非常短暂)为 http://localhost/my/path/fruits/page/2,然后恢复为 http://localhost/my/path/fruits/

注意:如果我不使用基本位置,似乎不会发生这种行为。但是,我需要使用基本位置,因为该应用程序位于服务器的 sub/sub/sub 目录中。

另外:如果我设置$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>

【问题讨论】:

  • 您找到任何可行的解决方案了吗?

标签: routing pagination angularjs


【解决方案1】:

也许这不会直接回答您关于它为什么以这种方式工作的问题,或者这是一个错误,因为我无法轻松重现它(我的意思是基本路径),但是我会尝试向您建议一些解决方案.

您应该尝试使用 ?page=4 之类的 url 参数,而不是使用 url change 来指示要与 reloadOnSearch: false 参数一起显示的页面,如下所示:

 $routeProvider
    .when('/', {
        templateUrl: 'fruits.html',
        controller: FruitCntl,
        reloadOnSearch: false
    })
    .otherwise({redirectTo:'/'})

我认为在您的情况下只有一条路线就足够了。现在我们必须更改分页逻辑以使用 $location 的搜索功能(而不是您的 $location.path):

$location.search('page', this.current_page);

这样,它会在您每次更改页面时更新您的页面,而无需创建新的控制器。它还简化了路由逻辑。希望对您有所帮助!

注意:我必须删除 $locationProvider.html5Mode(true).hashPrefix('!');,因为当我在本地运行它时它会破坏网站。

【讨论】:

    【解决方案2】:

    我也遇到了同样的问题,我终其一生都无法弄清楚出了什么问题。 对我有用的是更改将 ng-click 事件附加到按钮标签的锚标签。据我所知,当没有给出 href 属性以防止默认操作时,Angular 会修改锚标记的行为,因此如果您在 ng-click 事件处理程序中手动更新位置,这可能会干扰。这只是我的猜测,所以希望有人能够更好地解释。

    【讨论】:

    • 你知道如何解决这个问题吗?我遇到了你同样的情况。使用 angular 1.0.6 或 1.1.4,不会改变。
    • 我遇到了同样的问题,我在 URL 闪烁期间看到的是 URL 更改为 view%3Ditem123(其中 item123 是我通过 $location.path('/view' + item.name) 添加的项目 ID。然后它没有被拾取作为有效路由,“否则”将其重定向到根目录。仍然必须弄清楚如何以这种方式正确构建路径。
    • 如果由于 css 样式应用于一堆元素而将其更改为按钮标签太麻烦,您可以通过删除该“a”标签内的 href 属性来避免默认行为。我必须这样做,干杯。
    • 天啊!!!这让我困惑了好几个星期。非常感谢您对锚标签的洞察力。彻底解决了问题!
    【解决方案3】:

    您的浏览器正在回滚,因为 url 更改发生了两次,一次是触发 ng-click 函数,另一次是发生 a 标签的默认浏览器行为。

    这就是为什么您会在 url/view 中看到更新,然后它会恢复到原始状态。

    之所以会这样,是因为浏览器理解它应该这样做。

    可能的解决方案:

    按钮解决方案 正如在您可以触发按钮上的 ng-click 之前所建议的那样,这是有效的,因为该按钮没有有意义的 href 属性来更新 url。您可以向按钮添加 href,但它不会做任何事情。

    标签: 不要在 ng-click 中进行更新,而是避免使用函数并使 href 执行更改 url 的逻辑。这是一个更简洁的解决方案,因为您让浏览器执行更新 url 的标记的默认行为。

    我看到这样做的好处是任何人都可以一目了然地理解 url shceme,因此代码更易于维护。

    <a href="#/go/to/logic/5">Update to logic 5</a>
    

    带有 ng-click 的标签: 如果您绝对需要以编程方式进行更改,您应该做的是避免标签的默认行为。

    在 jQuery 中,您将绑定到单击事件并执行 event.preventDefault(),然后执行您的自定义逻辑。

    由于框架强加的逻辑分离,AngularJS 的方式有点不同,所以解决这个问题的方法是创建一个指令来执行 preventDefault。


    IgnoreClick 指令.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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-25
      • 1970-01-01
      • 1970-01-01
      • 2015-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      相关资源
      最近更新 更多