AngularJS:在不完全重新加载控制器的情况下更改哈希和路由

dou*_*oll 35 controller routes reload persist angularjs

我有一个控制器,有这样的路线:

#/用品/ 1234

我想在不完全重新加载控制器的情况下更改路径,因此我可以保持控制器中其他内容的位置不变(列出滚动)

我可以想到几种方法来做到这一点,但它们都非常难看.做这样的事情有最好的做法吗?我尝试使用reloadOnSearch:false,但它似乎没有改变任何东西.

Jen*_*son 34

有同样的挑战,

另一个StackOverflow响应中发现了一个黑客攻击

相当干净的解决方案 - 我所做的只是将这些行添加到设置$ location.path的控制器:

var lastRoute = $route.current;
$scope.$on('$locationChangeSuccess', function(event) {
    $route.current = lastRoute;
});
Run Code Online (Sandbox Code Playgroud)

..当然,确保$ route注入控制器.

但仍然感觉像"DoNotFollowRoutesOnPathChange"是AngularJS中缺少的功能.

/延

更新:由于有效地监听此事件会导致$ routeProvider配置的进一步使用,我不得不将此捕获限制为仅当前路径:

    var lastRoute = $route.current;
    if ($route.current.$route.templateUrl.indexOf('mycurrentpath') > 0) {
        $route.current = lastRoute;         
    }
Run Code Online (Sandbox Code Playgroud)

变得丑陋......

  • 在我的项目中尝试使用它之后,我决定听取`$ route.current.params.reload =='false'`,其中$ location位置更改发生在`$ location.url(' ?/ ...重载=假');`.这是明确的,如果templateUrl或控制器在另一条路线上碰巧相同,则没有奇怪的错误. (3认同)

Dai*_*wei 21

简要回答:

您可以使用$location.search()您提到的方法.你应该听取"$routeUpdate"范围而不是其他路线事件的事件.$ route API.

说明:

  1. 首先(您已经知道),添加reloadOnSearch: false到您的$routeProvider:

    $routeProvider.when('/somewhere', {
        controller: 'SomeCtrl',
        reloadOnSearch: false
    })
    
    Run Code Online (Sandbox Code Playgroud)
  2. 改变你的锚标记hrefng-hrefhref="#/somewhere?param=value"这将触发$routeChangeSuccess事件,如果路径部分(/somewhere)是不一样的当前位置.否则会触发$routeUpdate事件.

  3. 听取范围事件:

    $scope.$on("$routeUpdate", function(event, route) {
        // some code here
    });
    
    Run Code Online (Sandbox Code Playgroud)
  4. 如果要在代码中更改搜索参数,可以使用$location.search()方法.$ location.search API.


And*_*lin 8

如果将reloadOnSearch设置为false,则可以设置?a=b&c=durl 的部分而不重新加载.但是,如果没有重新加载,您无法巧妙地更改实际位置.

  • 嗯......我不知道这个应用程序是否理想,我宁愿保持与最终路线的哈希一致.我正在考虑使用一个控制器作为路径的路径,它将发送事件来显示和隐藏实际控制器,并且只有在第一次加载时才会完全更新它.这听起来很丑陋,所以我不确定它是不是最好的解决方案. (2认同)

tan*_*y_k 7

编辑

使用ngRoute时更好的方法:

/**
 * Add skipReload() to $location service.
 *
 * See https://github.com/angular/angular.js/issues/1699
 */
app.factory('location',
  ['$rootScope', '$route', '$location',
  function($rootScope, $route, $location) {

  $location.skipReload = function() {
    var lastRoute = $route.current;

    var deregister = $rootScope.$on('$locationChangeSuccess',
                                    function(e, absUrl, oldUrl) {
      console.log('location.skipReload', 'absUrl:', absUrl, 'oldUrl:', oldUrl);
      $route.current = lastRoute;
      deregister();
    });

    return $location;
  };

  return $location;
}]);
Run Code Online (Sandbox Code Playgroud)

如何使用:

app.controller('MyCtrl', ['$scope', 'location', function($scope, location) {
  $scope.submit = function() {
    location.skipReload().path(path);
  };
}]);
Run Code Online (Sandbox Code Playgroud)

老答案

我根据Jens X Augustsson的回答写了一个可重复使用的工厂:

app.factory('DoNotReloadCurrentTemplate', ['$route', function($route) {
  return function(scope) {
    var lastRoute = $route.current;
    scope.$on('$locationChangeSuccess', function() {
      if (lastRoute.$$route.templateUrl === $route.current.$$route.templateUrl) {
        console.log('DoNotReloadCurrentTemplate',
                    $route.current.$$route.templateUrl);
        $route.current = lastRoute;
      }
    });
  };
}]);
Run Code Online (Sandbox Code Playgroud)

适用于AngularJS 1.0.6

如何使用:

app.controller('MyCtrl',
  ['$scope', 'DoNotReloadCurrentTemplate',
  function($scope, DoNotReloadCurrentTemplate) {

  DoNotReloadCurrentTemplate($scope);
}]);
Run Code Online (Sandbox Code Playgroud)

AngularJS问题在这里:https://github.com/angular/angular.js/issues/1699