AngularJS 1.6:父组件存共享数据是否为反模式?parentView方式有何问题?
你说得完全对,这种直接通过thisView.parentView.variable读取上层组件数据、用this.parentView.changeVar(var)修改数据的方式,确实是AngularJS开发里的典型反模式,会给你的系统带来不少棘手的问题:
组件强耦合,维护成本飙升:子组件硬编码依赖父组件的结构和命名,比如
parentView这个标识、里面的variable变量和changeVar方法,一旦父组件的结构调整(比如重命名父组件实例、修改数据层级),所有依赖它的子组件都得跟着修改。这完全违背了组件“高内聚低耦合”的设计初衷,系统越复杂,维护起来越头疼。数据变更难以追踪,调试困难:当多个子组件都通过
parentView修改上层数据时,你很难快速定位到数据变化的源头。比如页面上某个数据突然变了,你得挨个检查所有可能修改它的子组件,再一层层往上追溯父组件的逻辑,排查bug的效率极低。组件复用性为零:子组件被死死绑定在特定的父组件结构上,没法直接复用到其他场景。比如你写了一个显示订单信息的子组件,想在另一个页面复用,但那个页面的父组件没有
parentView.order这种结构,你只能修改子组件的代码,完全失去了组件复用的价值。单元测试复杂度高:因为子组件直接依赖父组件的实例,写单元测试时你必须模拟整个父组件的结构,包括
parentView及其内部的变量和方法,测试用例会变得非常臃肿。而且只要父组件的结构变了,相关的测试用例就会失效,维护测试的成本也很高。
相比之下,用AngularJS服务来存储和管理共享数据是更合理的方案:
- 服务是单例的,能在整个应用内统一维护数据状态,所有组件都通过服务读写数据,数据流向清晰可追踪;
- 组件之间通过服务解耦,子组件不需要关心数据来自哪个父组件,只需要依赖服务,复用性大大提升;
- 可以在服务里封装数据修改的逻辑(比如数据验证、格式转换),确保所有组件对数据的操作都是一致的,避免出现各个组件随意修改数据导致的错误;
- 单元测试时只需要模拟服务的方法和数据,测试用例会更简洁、稳定。
内容的提问来源于stack exchange,提问作者tgb

