【问题标题】:Changing route in Angular causes re-evaluation of functions on the previous route's controller在 Angular 中更改路由会导致重新评估前一个路由控制器上的功能
【发布时间】:2015-03-21 08:48:32
【问题描述】:

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

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

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

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

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

我正在使用 Angular 1.3.10 和 ngRoute。

【问题讨论】:

  • $apply 对路线一无所知。应该怎么做?我宁愿担心在每个摘要周期中都会调用一个函数。这似乎不是一个特别的想法。
  • 这很难避免。这是一个示例:plnkr.co/edit/B4sH8bZhRJmRdTP4UWGt?p=preview 如果您单击“第二个”链接,Angular 仍会调用“第一个()” - 检查控制台输出。另外,我不知道为什么它会调用 3 次,但这是另一个问题。
  • 理想情况下,pathForItem 是一个值,而不是一个函数。当然,我不知道您的情况,但我认为pathForItem 的返回值不会随着每个摘要周期而变化。我的印象是它取决于登录的用户,这意味着该值根本不会改变。
  • 是的,我可以使用一次性绑定来避免它,但我仍然认为我需要担心这些东西真的很奇怪......

标签: javascript angularjs angularjs-scope ngroute


【解决方案1】:

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

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

当html5Mode启用时,启用/禁用相对链接的url重写

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

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

请参阅docs 了解更多信息。如果您需要这种行为,那么您可以为您的情况准备函数或将$scope.pathForItem 设为一个值。我还是推荐后者。

【讨论】:

  • 谢谢。由于pathForItem 为每个项目返回不同的值,我认为最好使用一次性绑定 - 这也应该可以轻松处理项目数组被修改的情况。
猜你喜欢
  • 1970-01-01
  • 2017-09-19
  • 2020-02-27
  • 2015-10-27
  • 2014-09-16
  • 2017-01-17
  • 1970-01-01
  • 2016-07-04
  • 1970-01-01
相关资源
最近更新 更多