38

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

想法是使用 $http 加载的:

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

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

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

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

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

我试过听 $routeChangeStart 做一个 preventDefault:

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

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

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

4

7 回答 7

93

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

设置您的路线以忽略查询参数更改:

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

并在您的应用更新$location中:

...
$location.search('page', pageNumber);
...
于 2012-09-18T16:29:02.427 回答
31

这篇博文

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

但是,有一种简单的方法可以将其短路。Angular 监视位置变化(无论是通过在位置栏中键入、单击链接还是通过 设置位置来完成 $location.path())。当它感知到这种变化时,它会广播一个事件$locationChangeSuccess,并开始路由过程。我们所做的是捕获事件并将路线重置为之前的路线。

function MyCtrl($route, $scope) {
    var lastRoute = $route.current;
    $scope.$on('$locationChangeSuccess', function(event) {
        $route.current = lastRoute;
    });
}
于 2012-09-14T17:16:09.430 回答
3

我的解决方案是使用 $routeChangeStart,因为它为您提供了“下一个”和“最后一个”路由,您可以在不需要额外变量(如 $locationChangeSuccess)的情况下比较它们。

好处是能够访问“next”和“last”路由上的“params”属性,就像next.params.yourproperty您使用“/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 应该提供一种控制它的方法,现在他们假设每当您更改浏览器的位置时,您都想更改路线。

于 2014-02-11T10:43:13.220 回答
1

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

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

请记住,在使用$location.path. 这是为了兼容 HTML5 模式。

于 2012-09-15T12:16:12.873 回答
0

$locationChangeSuccess 事件是一种蛮力的做法,但我发现检查路径可以避免在路由路径模板未更改时重新加载页面,但在切换到不同的路由模板时重新加载页面:

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

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

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

于 2014-03-24T15:57:19.507 回答
0

在 AngularJS V1.7.1中,$route增加了对reloadOnUrl配置选项的支持。

如果 route设置/foo/:idreloadOnUrl= false,那么从/foo/id1to移动/foo/id2只会广播一个$routeUpdate事件,并且不会重新加载视图并重新实例化控制器。

于 2020-01-13T00:29:08.330 回答
0

我需要这样做,但在尝试让$locationChange~事件使其正常工作后,我了解到您实际上可以在routeusing resolve.

$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;
            }]
        }
    }
);
于 2015-12-14T03:07:21.317 回答