你可能经常听到有人这么说
Angular在3年后等你。
Angular更适合大型或企业项目
Angular提供了出色的更新体验
…
在这篇文章中,我将向您展示为什么我认为Angular不如您在2023 Angular 15、16之前听到的那么好。
当然,在将Angular与其他框架/lib进行比较时,我不可能做到100%公平。此外,因为我试图在2023年之前演示Angular并不是那么好,所以我会过多地关注缺点。这对Angular来说是不公平的。2023年之后,Angular变得更好了,但我将在其他文章中介绍这些部分。
公平地说,我将在2023/8/15创建两个项目,一个用于Angular,另一个用于Vue。
For Angular, I’m creating with ng new my-app-angular
with @angular/cli@16.2.0
.
For Vue, I’m creating with npm create vue@latest
with create-vue@3.7.2
.
我将一步一步地演示它。
创建新项目时模板过于简单
使用Angular CLI创建新项目时,我有两个选项
- 需要路由
- CSS格式

While with Vue CLI,

除了2个选项,我还有4个以上的选项
- state-management lib
- e2e test lib
ESLint
Prettier
for code formatting- ……
老实说,在我看来,对于一个大型或企业项目来说,配置以上4个选项很重要。
如果开发人员不是高级或专业的前端工程师,或者只是想节省一些时间,而CLI不提供这些选项,那么它们很容易丢失。
如果他们不是在一个大项目开始时建立的,那么让所有团队成员就一个特定的解决方案达成一致并不容易。有些人喜欢这个国家管理库,而另一些人则喜欢另一个。有些人喜欢半成品,而另一些人则不…
即使幸运的是,开发人员在迭代中设置了它,仍然有一些遗留代码需要迁移。
顺便说一句,Angular直到现在还没有官方的状态管理解决方案。由于这个问题,Angular在2022年将此功能添加到了积压工作中。到目前为止,Angular最出色的状态管理解决方案是ngrx。还有许多人将自己设计的状态管理库与RxJs和DI一起使用。
默认项目文件夹结构过于简单
对于Angular,在找到CodingStyleGuide一章之前,我甚至不知道如何使用模板进行编码。

- 路由器视图放在哪里?
- 将共享代码放在哪里?
- …
而对于Vue,我认为开发人员可以立即编写代码。

无论如何,我将按照Angular样式指南创建一个英雄特性模块。

演示代码是从Angular主页演示中复制的。
这是UI:

默认更改检测策略是性能杀手
你有没有注意到当页面被加载时,这个函数在控制台被调用了多少次?6*9=54次!这是代码
And if you move your mouse from top to bottom, the function will be triggered 2*9*9 times!

在这种情况下,我们可以使用OnPush策略。

isSensitiveHeroName
will be triggered 9 times in the first time and 9*9 times for mouseenter
event.

因此,使用OnPush策略,性能提高了1200%。事实上,如果我们想将默认策略更改为OnPush,我们需要应用更多的更改,而不仅仅是这个演示中的一行。
对于这种情况,Angular有一个更好的解决方案。

现在,我们有了更好的表现,也许是最好的表现。这就是为什么你经常可以在Angular社区中看到这一点。
从不调用模板中的函数
好的。这是我关心的问题
避免在模板中使用函数真的好吗?
为了获得更好的性能,我们定义了一个派生状态isSensitive。所以,每次我们更改英雄的名字时,我们都需要更新isSensitive。
在实际应用程序中,会有许多派生状态依赖于2个或多个其他状态。因此,我们需要添加越来越多的代码来保持当前的性能,这将很快带来错误和维护问题。
可能还有其他方法可以在不编写更多代码的情况下保持性能。但这是我关心的问题
Angular开发人员编写高性能、易于维护的代码需要多长时间?1个月还是1年?
幸运的是,Angular在2023年推出了Signals,目前正在开发者预览中。Signals允许您编写高性能且易于维护的代码。
复杂的NgModule
现在,让我们假设我想使用HeroesModule之外的HeroListComponent。我需要将其从HeroesModule导出,然后将HeroesMode导入另一个模块(假设为AppModule)。

我只能看到一个优点。如果我想使用从HeroesModule导出的组件,我不需要再次将组件导入AppModule。
然而,我看到了许多缺点。
对于开发人员来说,要知道AppModule从HeroesModule导入了多少东西并不容易。只有Angular知道。
因为组件必须在模块中声明,所以开发人员很难知道组件在模块中依赖于多少东西。例如,HeroListComponent是否依赖于CommonModule和HeroesRoutingModule?我们需要检查一下。
因此,如果您将组件从一个模块移动到另一个模块,但它不起作用,这是很常见的,因为您需要找出组件需要什么依赖项,并移动依赖项。因为依赖项没有在组件中声明。
总之,一个组件本身无法工作,如果你来自其他框架,这很难想象。
幸运的是,我们在中获得了独立组件angular@15到2022年底。Angular团队甚至为您提供了一个从NgModule迁移到独立组件的工具。
与RxJs深度绑定
许多Angular API都是通过Observable公开的,甚至是HttpClient。然而,对于初学者来说,用RxJs编写bug较少的代码并不容易。
RxJs声明风格中需要注意的事项
例如,以前的HeroListComponent是用声明性样式实现的。如果我们删除模板中的英雄$|async,那么service.getHeroes将永远不会被再次调用。如果你是Angular或RxJs的新手,这可能会让你大吃一惊。

此外,如果service.getHeroes抛出一次错误,该函数将不再工作。这就是为什么您经常可以在声明性代码中看到catchError(() => EMPTY)
。

RxJs命令式风格中需要谨慎的事情
事实上,许多开发人员都在使用命令式编程。在这种情况下,HeroListComponent会像

在模板中,需要将heroes$|async更改为heroes。
然而,它有错误。就像我们在addEventListener之后需要removeEventListener一样,我们也需要取消订阅或使用takeUntilDestroyed。

然而,直到现在,takeUntilDestroyed还在开发者预览中。在2023年之前,我们需要添加更多的代码。还有一点,这种方式对OnPush策略不友好。
简短结论
正如您所看到的,与RxJs的深度绑定使开发人员更容易出错或编写性能较差的代码。
我确实认为RxJs功能强大,特别适合边缘情况。然而,拥有强大的工具并不意味着我们需要在所有情况下都使用它。许多没有RxJ的框架/libs/项目都运行得很好。
此外,我没有提到开发人员需要从RxJ中了解的内容以及它带来的非常侵入性的代码风格。
Angular的当前状态
正如您所看到的,Angular带来了许多新的解决方案。这是一件好事,但如果他们不及时指出建议的解决方案,那可能是一件坏事。社区可能会比以前更加分裂。
- 声明式或命令式编程
- 更少或更多RxJ
- 默认或OnPush
- NgModule或独立
- zone.js或Singals
- …
在它们之间进行选择将导致不同的样式,这也使得代码难以维护。
前两个选择已经使社区分裂。现在我们有更多。
在我看来,
- 独立+Singals是Angular的未来。
- RxJs对于Angular是可选的。
- 将提供官方的国家管理解决方案。
- Angular将更像其他框架/lib。
Angular已经做出了很好的选择,比如选择typescript,但选择NgModule和zone.js可能并没有那么成功。即使是内置的RxJs API也可能不是一个好的解决方案。
Angular在3年内不会等待其他框架/lib。
他正在做出进步和选择。许多框架和开发人员没有选择的一些解决方案往往意味着它们可能不太适合前端开发。在这些情况下,Angular也在向其他框架/lib学习,而不是等待并坚持自己的方向是正确的。
实际上,框架/lib都在相互学习。学习和提高自己比认为我是最好的要好得多。
- 登录 发表评论