当reloadOnSearch为false时,$ location.search上的AngularJs $ watch不起作用

我的routeProvider路由有reloadOnSearch设置为false

$routeProvider .when( "/film/list", { templateUrl: '/film/list.html', controller: FilmListController, reloadOnSearch: false } .... ) 

我这样做是因为我不希望整个控制器在查询string更改后重新加载,但我仍然使用它,并且URL如下所示: film/list?sort=isbn&order=asc&offset=0 。 现在每当查询string更改,我想从我的控制器调用一个函数。 所以我试图在控制器中设置$ watch

 $scope.location = $location; $scope.$watch( 'location.search()', function( search) { $scope.list(); }); 

但是这不起作用。 如果我将$ watch设置为查看查询string的单个参数的更改,那么它将起作用。 但是我不想为我的查询string的每个参数设置$ watch。 我现在使用的解决scheme是这样的:

 $scope.location = $location; $scope.$watch( 'location.url()', function( url ) { if($location.path() == '/film/list') $scope.list(); }); 

因此,我没有注意search,而是观察整个url,然后检查path是否是我在routeProvider中设置的path,以有条件地调用该函数。 我不喜欢这个解决scheme是我必须明确键入$ location.path的值来匹配。

任何人都可以提出一个更好的解决scheme,也许可以解释为什么$ watch不工作$ location.search()

您可以在您的控制器中侦听$routeUpdate事件:

 $scope.$on('$routeUpdate', function(){ $scope.sort = $location.search().sort; $scope.order = $location.search().order; $scope.offset = $location.search().offset; }); 

如果你不使用Angular的路由分辨率,或者你只是想知道$ location的位置发生变化,那么只是为了这个目的

 $rootScope.$on('$locationChangeSuccess', function(event){ var url = $location.url(), params = $location.search(); }) 

Stewies的回答是正确的,你应该听取$routeUpdate事件,因为它更有效率。

但要回答你的手表为什么不工作, 当你观看location.search() ,你正在观察search方法返回的引用是否相同。 每当你调用它时,它都会返回同一个对象的引用,这就是为什么你的手表没有被触发。 也就是说,即使search参数发生变化,仍然是返回的对象。 为了解决这个问题,你可以把第三个参数传给$watch 。 这将告诉Angular通过价值进行比较,而不是参考。 但是在创build这样的手表时要小心,因为它们会消耗更多的内存,并且需要更长的时间来执行。 所以这就是为什么你应该像stewie说的那样做。

使用

 $scope.$watch(function(){ return $location.search() }, function(params){ console.log(params); }); 

代替。

在控制器上routeUpdate的更改,如下所示:

  $scope.$watch('$routeUpdate', function(){ $scope.sort = $location.search().sort; $scope.order = $location.search().order; });