【问题标题】:AngularJS Paging with $location.path but no ngView reloadAngularJS 分页与 $location.path 但没有 ngView 重新加载
【发布时间】:2012-09-07 12:08:44
【问题描述】:

我的单页应用程序加载了一个主页,我想展示一系列想法。每个想法都显示在动画 Flash 容器中,并显示动画以在想法之间循环。

想法是使用 $http 加载的:

$scope.flash = new FlashInterface scope:$scope,location:$location

$http.get("/competition.json")
  .success (data) ->
    $scope.flash._init data

但是,为了从历史导航和用户体验中受益,我希望使用 $location 更新地址栏以显示每个想法的正确 url:

$location.path "/i/#{idea.code}"
$scope.$apply()

我在这里调用 $apply 是因为这个事件来自 AngularJS 上下文之外,即 Flash。我希望当前的控制器/视图保留并且视图不重新加载。这很糟糕,因为重新加载视图会导致整个 Flash 对象被丢弃,并且重新开始预加载循环。

我已经尝试监听 $routeChangeStart 来做一个 preventDefault:

$scope.$on "$routeChangeStart", (ev,next,current) ->
  ev.preventDefault()
$scope.$on "$routeChangeSuccess", (ev,current) ->
  ev.preventDefault()

但无济于事。如果我能找到一种在更改 $location.path 时覆盖视图重新加载的方法,那么整个事情就会变得很糟糕。

我仍然非常熟悉 AngularJS,所以我很高兴有任何关于如何构建应用程序以实现我的目标的指示!

【问题讨论】:

  • 我迟到了,但我刚刚遇到了类似的问题。您是否有理由不能将ideas 放在ng-view 指令之外并给它们自己的控制器,该控制器通过范围继承与ng-view 内的控制器交互?我主要是问,因为这是我解决自己问题的方法,我想知道它是否有任何缺点,或者我是否应该切换到接受的答案。
  • 如果我今天再次解决这个问题,我会很想使用具有分层视图功能的 ui-router。我不确定这是否能解决我在这里遇到的特定 URL 问题,需要更多研究一段时间......!
  • 好的,感谢您为我指明方向,感谢您回复这么晚的评论!

标签: angularjs ngroute


【解决方案1】:

来自this blog post

默认情况下,所有位置更改都会经过路由过程,即 更新角度视图。

不过,有一种简单的方法可以将其短路。角度手表 对于位置更改(无论是通过键入 位置栏,单击链接或通过设置位置 $location.path())。当它感知到这种变化时,它会广播一个 事件$locationChangeSuccess,并开始路由过程。什么 我们所做的是捕获事件并将路线重置为原来的样子 以前。

function MyCtrl($route, $scope) {
    var lastRoute = $route.current;
    $scope.$on('$locationChangeSuccess', function(event) {
        $route.current = lastRoute;
    });
}

【讨论】:

  • 感谢您,这听起来与我正在寻找的解决方案一模一样。我已经浏览了博客文章并且玩得很好。不幸的是,它似乎不起作用。我尝试将代码放在$routeChangeStart 中,看看是否会有所作为,但无济于事。是不是我错过了一些巫术?
  • 另一个想法:尝试设置 reloadOnSearch=false, docs.angularjs.org/api/ng.$routeProvider 另见github.com/angular/angular.js/pull/1151
  • 这是一个可怕的、可怕的黑客攻击......但它确实有效。直到 Angular 提供某种方法来将位置更新事件与重新加载分离(不幸的是,阻止默认值会阻止 url 彻底更改),这就是我们正在使用的。是的,如果您需要更改的内容仅限于搜索参数,那么 reloadOnSearch=false 效果很好。我们的问题在于可书签标签的哈希值。
  • @mark 谢谢你,我正在做一个不相关的项目,这使我的程序正常工作。谢谢!
  • 这似乎适用于所有位置更改。因此,如果您想要通过角度路由进行特定链接,它们将被破坏。此外,后退按钮将不再起作用。
【解决方案2】:

您应该通过依赖注入加载$location 并使用以下内容:

$scope.apply(function () {
    $location.path("yourPath");
}

请记住,在使用$location.path 时,您应该使用井号标签(#)。这是为了兼容 HTML5 模式。

【讨论】:

  • 感谢您的提示。我认为我正在正确加载 $location IndexController = ($scope,$http,$location,$route) -> 并且我已按照您的建议更新了应用代码。我不太确定这有什么不同,你能详细说明一下吗?
【解决方案3】:

不用更新路径,只需用页码更新查询参数。

设置路由以忽略查询参数更改:

....
$routeProvider.when('/foo', {..., reloadOnSearch: false})
....

并在您的应用中更新$location

...
$location.search('page', pageNumber);
...

【讨论】:

  • 感谢您的提示,伊戈尔。我之前发现并打折了这种方法,因为我更喜欢 URL 之类的 '/idea/Acas' 而不是 '/foo?idea=Acas'。然而,它确实具有工作的优点,并且在实用主义者的世界中,工作胜过完美!
  • 完美,非常感谢这个提示。另外我想注意,如果您想检测参数更改,您可以使用: $scope.$on("$routeUpdate", function(){ // 搜索参数已更改 })
  • 这就是答案!我发现所有这些其他答案都可以解决 $route 和 $state 的问题,这很简单,可以完成工作!
【解决方案4】:

我的解决方案是使用 $routeChangeStart,因为它为您提供了“下一个”和“最后一个”路线,您可以比较它们而不需要像 $locationChangeSuccess 这样的额外变量。

当您使用“/property/value” URL 样式并且当然使用 $location.url$location.path 更改 URL 而不是 $location.search(),这取决于 "?property=value" URL 样式。

在我的例子中,我不仅使用它,而且还防止路由改变是控制器没有改变:

$scope.$on('$routeChangeStart',function(e,next,last){
  if(next.$$route.controller === last.$$route.controller){
    e.preventDefault();
    $route.current = last.$$route;
    //do whatever you want in here!
  }
});

我个人觉得 AngularJS 应该提供一种控制它的方法,现在他们假设每当您更改浏览器的位置时,您都想更改路由。

【讨论】:

  • 当我尝试在 AngularJS 1.2.6 的控制器中使用它时,这对我不起作用。我认为这与 $routeChangeStart 是不可预防的广播有关:stackoverflow.com/a/14895801/959140
【解决方案5】:

$locationChangeSuccess 事件有点蛮力的做法,但是我发现检查路径可以避免在路由路径模板不变的情况下页面重新加载,但在切换时重新加载页面到不同的路线模板:

var lastRoute = $route.current;
$scope.$on('$locationChangeSuccess', function (event) {
    if (lastRoute.$$route.originalPath === $route.current.$$route.originalPath) {
        $route.current = lastRoute;
    }
});

将该代码添加到特定控制器使重新加载更加智能。

编辑:虽然这使它更容易一些,但我最终不喜欢我为保持 URL 友好而编写的代码的复杂性。最后,我只是切换到一个搜索参数,而 angular 处理得更好。

【讨论】:

    【解决方案6】:

    我需要这样做,但在尝试让 $locationChange~ 事件让它工作后,我了解到您实际上可以使用 resolveroute 上执行此操作。

    $routeProvider.when(
        '/page',
        {
            templateUrl : 'partial.html',
            controller : 'PageCtrl',
            resolve : {
                load : ['$q', function($q) {
                    var defer = $q.defer();
    
                    if (/*you only changed the idea thingo*/)
                        //dont reload the view
                        defer.reject('');
                    //otherwise, load the view
                    else
                        defer.resolve();
    
                    return defer.promise;
                }]
            }
        }
    );
    

    【讨论】:

      【解决方案7】:

      使用 AngularJS V1.7.1$route 增加了对 reloadOnUrl 配置选项的支持。

      如果路由/foo/:id 设置了reloadOnUrl = false,则从/foo/id1 移动到/foo/id2 只会广播$routeUpdate 事件,并且不会重新加载视图并重新实例化控制器。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-13
        • 1970-01-01
        • 1970-01-01
        • 2014-07-02
        • 2014-03-20
        • 1970-01-01
        • 2017-04-10
        • 1970-01-01
        相关资源
        最近更新 更多