在 Angular 中更改路线会导致重新评估先前路线控制器上的功能

Changing route in Angular causes re-evaluation of functions on the previous route's controller

我有一条路线(例如 /items),它的控制器有

$scope.pathForItem = function (item) {...}

方法,在模板中用于显示列表中每个项目的路径。当我在此页面上并单击任何 link 以更改路线时,Angular 会在其代码中的某处调用 $rootScope.$apply(),这会导致重新评估 [=] 上定义的某些函数14=]。问题在于,这也会重新评估先前路由控制器范围内的功能,因此会为页面上的每个项目再次调用 pathForItem 一次。通常这不是什么大问题 - 这是不必要的,但不会导致任何错误。

但是,当我尝试注销时它会导致错误。 pathForItem 假设 user 对象存在(它从 authService 获得)并且它通常有效,因为我们确保用户存在于此路由的 resolve 函数中。现在,当有人尝试注销时,Angular 调用 $rootScope.$apply() 并再次尝试为所有项目调用 pathForItem。然而,在中间的某个地方,用户最终被删除,authService.currentUser() 开始返回 null 并且所有对 pathForItem 的进一步调用都会引发错误...

真的应该这样吗? Angular 的 $rootScope.$apply 是否也应该为之前路由的控制器调用函数?是否有一些通用的解决方法,或者我是否必须确保所有控制器中的所有函数也在模板中使用,始终检查它们使用的所有对象是否确实存在,即使我已经在 resolve 中检查过了功能?

我正在使用 Angular 1.3.10 和 ngRoute。

(插值-)表达式中的函数在每个摘要循环中都会被调用,您不可能提前知道这将在何时发生。因此,您的函数必须做好准备,不仅要比您预期的更频繁地被调用,而且还要在意想不到的时候被调用。

你的问题的罪魁祸首是 html5 模式。有一个重写链接和调用的全局事件处理程序 $apply。问题是即使未启用 html5 模式,它也会完成。我认为这是一个错误,因为文档说

When html5Mode is enabled, enables/disables url rewriting for relative links

无论如何,您可以在配置块中关闭此行为:

$locationProvider.html5Mode({rewriteLinks: false});

有关详细信息,请参阅 docs。如果你需要这种行为,那么你要么为你的情况准备你的函数,要么让 $scope.pathForItem 成为一个值。反正我推荐后一种。