在控制器中使用angular的$ watch是反模式吗?

ten*_*gen 30 anti-patterns angularjs

在我永无止境的追求以"正确"的角度方式做事的过程中,我一直在阅读很多关于如何让控制器观察角度服务中的模型变化.

一些网站称在控制器上使用$ watch是完全错误的:

请勿在控制器中使用$ watch.几乎在所有情况下都很难测试并且完全没有必要.使用范围上的方法来更新手表正在更改的值.

只要你自己清理完以后其他人看起来很好:

$ watch函数本身返回一个函数,该函数在调用时解除$ watch的绑定.因此,当不再需要$ watch时,我们只需调用$ watch返回的函数.

有一些问题其他声誉良好的网站似乎正确地说,在控制器中使用$ watch是注意角度服务维护模型中的变化的好方法.

https://github.com/angular/angular.js/wiki/Best-Practices网站,我想我们可以给多一点的重量,直接说是$范围.$手表应该更换事件的需要.但是,对于处理超过100个模型和REST端点的复杂SPA,选择使用$ watch来避免事件$broadcast/$emit可能最终导致大量手表.另一方面,如果我们不使用$ watch,对于非平凡的应用程序,我们最终会产生大量的意大利面条.

这是一个输/输的情况吗?这是事件和手表之间的错误选择吗?我知道你可以在很多情况下使用双向绑定,但有时你只需要一种方法来监听变化.

编辑

Ilan Frumer的评论让我重新思考我的要求,所以也许不仅仅是询问在控制器中使用$ watch是否主观好/坏,让我用这样的方式提出问题:

哪种实现可能会首先造成性能瓶颈?让控制器监听事件(必须已经广播/发出),或者$watch在控制器中设置-es.请记住,大型应用程序.

哪个实现首先会引起维护问题:$watch-es或事件?可以说,无论哪种方式都存在耦合(紧密/松散)......事件观察者需要知道要监听什么,而且$watch- 外部值(如MyDataService.getAccountNumber())需要知道在$ scope范围之外发生的事情.

**一年后编辑**

自从我提出这个问题以来,Angular已经改变/改进了很多,但我仍然得到+ 1,所以我想在提到角度团队的代码时会提到这一点,我看到了控制器中观察者的模式(或者有一个范围被销毁的指令):

$scope.$on('$destroy', $scope.$watch('scopeVariable', functionIWantToCall)); 这需要$ watch函数返回的内容 - 可以调用以取消注册观察者的函数 - 并在控制器被销毁时将其提供给事件处理程序.这会自动清理观察者.

无论控制器中的手表是否具有代码味道,如果您使用它们,我相信角度团队对此模式的使用应该作为如何使用它们的强烈建议.

谢谢!

JHi*_*son 5

我同时使用它们,因为老实说,我认为它们是针对不同问题的不同工具.

我将从我构建的应用程序中给出一个示例.我有一个复杂的WebSocket服务,它从Web套接字服务器接收动态数据模型.服务本身并不关心模型的样子,当然,控制器确实如此.

当启动控制器时,它$watch在服务数据对象上设置一个,以便它知道它的特定数据对象何时到达(就像等待Service.data.foo存在一样.一旦该模型出现,它就能够绑定到它并且对它进行双向数据绑定,手表变得过时,它被摧毁了.

另一方面,该服务也负责广播某些事件,因为有时客户端会从服务器接收文字命令.例如,服务器可能会请求客户端在整个应用程序中发送存储在"$ rootScope"中的一些元数据.一个.on() 成立的$rootScope过程 module.run()步骤倾听来自服务器的命令,从其他服务收集所需的信息,并调用WebSocket的服务回报作为请求发送数据.或者,如果我使用a完成此操作$watch(),我需要设置某种任意变量供它观看,就像metadataRequests我每次收到请求时需要增加的那样.A broadcast实现同样的事情,而不必像我们的变量那样生活在永久记忆中.

本质上,我使用a $watch()当有一个特定的值我希望看到变化时(特别是如果我需要知道前后值),如果有更多的高级条件已经满足,我会使用事件控制器需要知道.

关于性能,我不能告诉你哪个会首先出现瓶颈,但我觉得这样想会让你利用每个功能最强的功能.例如,如果您使用$on()而不是$watch()查找数据中的更改,则无法访问更改前后的值,这可能会限制您尝试执行的操作.

  • 我最终选择了这条路线,这也与@calebboyd发布的类似:每个都有它的位置.我从你的答案中拿走了两件事......当看到旧的和新的价值观时,观看是否有用,并且有广播的服务.我的实现是让服务和控制器双向绑定,并让服务监听几个特定事件,而不是让所有控制器监听事件,然后轮询服务以获取新数据.这为我节省了一堆代码......谢谢 (2认同)