angular技巧

This summer me and Roman started a series of tweets with helpful tips and tricks about Angular. It was met well by the community so I decided to write an article follow-up. Here are 5 generalized advises I want to give to Angular developers across the globe. These advises are backed by some concrete examples pulled from our Twitter activity. They can help you improve your developer skills or give you some practical tricks at the very least.

今年夏天,我和罗曼(Roman)开始了一系列推文,其中包含有关Angular的有用技巧。 社区对此表示满意,因此我决定写一篇文章跟进。 这里是我想给全球Angular开发人员的5条概括性建议。 这些建议得到了Twitter活动中一些具体示例的支持。 它们可以帮助您提高开发人员的技能,或者至少给您一些实用的技巧。

1.了解变更检测在Angular中的工作方式 (1. Know how change detection works in Angular)

There are many great articles going deep into change detection mechanism. Like this one. So let’s just recap the basics quickly and get to the tips.

有很多伟大的文章深入探讨了变更检测机制。 喜欢这个 。 因此,让我们快速回顾一下基础知识并掌握技巧。

回顾 (Recap)

Angular has two change detection modes: Default and OnPush. First one triggers change detection for every tick happened anywhere in the app. Former only marks view for checking if an event has happened in this view or if input data has changed.

Angular有两种变化检测模式: DefaultOnPush 。 第一个触发了针对应用程序中任何位置发生的每个滴答的变化检测。 前仅标记视图用于检查此视图中是否发生了事件或输入数据是否已更改。

Default vs OnPush (Default vs OnPush)

There’s really no reason for you to use Default. All you need to do is write your code the way framework expects it to and you won’t get into trouble with OnPush. This means, you should never mutate your data. If your input arrays or objects change immutably, OnPush would pick this up and refresh the view.

您实际上没有理由使用Default 。 您所需要做的就是按照框架期望的方式编写代码,而不会遇到OnPush麻烦。 这意味着,您永远都不更改您的数据 。 如果您的输入数组或对象不变,则OnPush会选择并刷新视图。

When you subscribe to events with @HostListener Angular has got you covered as well. But what if you are working with RxJS streams? You can always inject ChangeDetectorRef and do markForCheck() when you need it. But a declarative option would be to end up with async pipe in your template. It would trigger change detection on each emit.

当您使用@HostListener订阅事件时,Angular也@HostListener您的要求。 但是,如果您正在使用RxJS流,该怎么办? 你可以随时注入ChangeDetectorRefmarkForCheck()当你需要它。 但是声明性的选择是在模板中以async管道结束。 它将触发每次发射的变化检测。

You might have seen this pattern:

您可能已经看到了这种模式:

<div *ngIf="stream$ | async as result">  ...</div>

But what do you do when you need falsy results too? You can strip condition logic from ngIf and create a simple structural directive. It would be used only to add context to the view:

但是,当您也需要虚假的结果时该怎么办? 您可以从ngIf剥离条件逻辑,并创建一个简单的结构指令。 它仅用于向视图添加上下文:

演示地址

NgZone (NgZone)

If you cannot fully switch to OnPush there are still things you could optimize. You can inject NgZone and do performance sensitive actions in .runOutsideAngular(). This way there will be no extra ticks in the change detection mechanism. Even components with Default strategy will not perform change detection cycle. You should do this for events that trigger rapidly like mousemove, scroll. To do it declaratively with RxJS streams you can create two operators. One for leaving the zone and another to return to it if you need to trigger change detection:

如果您不能完全切换到OnPush ,仍然可以优化某些功能。 您可以在.runOutsideAngular()注入NgZone并执行对性能敏感的操作。 这样,更改检测机制中就不会有多余的滴答声。 即使具有Default策略的组件也不会执行更改检测周期。 您应该对快速触发的事件(例如mousemovescroll执行此操作。 要使用RxJS流声明性地执行此操作,可以创建两个运算符。 一个用于离开区域,另一个用于返回区域,如果您需要触发更改检测:

演示地址

Another option you can have with @HostListener decorator is custom event manager plugin. We released an open-source library called ng-event-plugins. It allows you to filter out unnecessary change detection cycles. Read more about it in this article.

@HostListener装饰器可以提供的另一个选项是自定义事件管理器插件。 我们发布了一个名为ng-event-plugins的开源库。 它使您可以过滤掉不必要的变更检测周期。 在本文中阅读有关它的更多信息。

2.学习RxJS。 认真! (2. Learn RxJS. Seriously!)

RxJS is a very powerful tool. We all use it to some extent when working with Angular but really mastering it can help you a lot. From very simple streams that allow you to reload your component…

RxJS是一个非常强大的工具。 在使用Angular时,我们都在某种程度上使用了它,但真正掌握它可以为您带来很多帮助。 通过非常简单的流,可让您重新加载组件…

演示地址

…to complex operators combination. Like this example recognizing various types of scroll:

…复杂的运营商组合。 像此示例一样,可以识别各种类型的滚动:

演示地址

Just take a look how easy it is to create a sticky header that disappears when you scroll down. A little bit of CSS and pretty basic RxJS:

只需看看创建粘性标头是多么容易,当向下滚动时,该标头就消失了。 一点CSS和相当基本的RxJS:

演示地址

I cannot stress enough how important RxJS knowledge is to an Angular developer long term. While it’s simple on the first look, RxJS requires a little bit of paradigm shift. You need to start thinking in terms of streams. But once you do, your code would become more declarative and easier to maintain.

我不能足够强调RxJS知识对Angular开发人员的长期重要性。 乍一看很简单,但RxJS需要一些范式转换。 您需要开始考虑流。 但是,一旦这样做,您的代码将变得更具声明性且更易于维护。

There is not much I can suggest here other than practice. If you see a case that you can solve with RxJS — try to do so. Avoid side-effects and nested subscribes. Keep your streams organized and watch out for memory leaks (read further).

除了练习,我在这里没有其他建议。 如果您发现可以使用RxJS解决的情况,请尝试这样做。 避免副作用和嵌套订阅。 保持流井井有条,并注意内存泄漏(进一步阅读)。

3.最大输出TypeScript (3. Max out TypeScript)

We all use TypeScript in our Angular applications. But to get the most of it we need to push it to the limits. I rarely see projects with enabled strict: true. This is something you totally should do. It will save you from lots of cannot read property of nulls and undefined is not a functions.

我们都在Angular应用程序中使用TypeScript。 但是要充分利用它,我们需要将其推向极限。 我很少看到启用了strict: true项目strict: true 。 这是您完全应该做的事情。 它将使您免于cannot read property of nullcannot read property of nullundefined is not a function s的麻烦。

泛型 (Generics)

In TypeScript we can use generics when the type we work with is unclear. Combination of generics, overloads and type narrowing can make a pretty solid API. You almost never will have to typecast. Take a look at this example of strongly typed RxJS method fromEvent:

在TypeScript中,当我们使用的类型不清楚时,可以使用泛型。 泛型,重载和类型缩小的组合可以使API更加可靠。 您几乎永远不必打字。 看一下来自Event的强类型RxJS方法的fromEvent

演示地址

With it you can be sure that target in the event has the same type as the element you listen the event on. And event has properly narrowed type.

有了它,您可以确保事件中的目标与您监听事件的元素具有相同的类型。 事件已适当缩小类型。

Generics based APIs have the benefit of being data-model agnostic. This means people can use it without being forced to a particular interface

基于泛型的API的优点是与数据模型无关。 这意味着人们可以使用它而不必被迫使用特定的界面

There are articles dealing with things like type inference, advanced types, unions. I suggest you educate yourself in the subject, it would help you make robust code in the long run. My one last advice here is never use any. You can almost always replace it with generic or unknown which is a safer version of any.

有些文章涉及类型推断,高级类型,联合。 我建议您对本学科进行教育,从长远来看,这将帮助您编写可靠的代码。 我最后的建议是永远不要使用 any建议。 您几乎总是可以将其替换为通用或unknown版本,这是any版本的安全版本。

装饰工 (Decorators)

Don’t forget about other TypeScript features, such as decorators. When used well, they can really improve your code. There are cases when type is correct, but logically value is unacceptable. Like when you have a number input for quantity — you cannot really have negative or decimal values. But according to TypeScript they are correct. You can protect your components for such invalid inputs with assertion decorator:

不要忘记其他TypeScript功能,例如装饰器。 如果使用得当,它们可以真正改善您的代码。 在某些情况下,类型是正确的,但逻辑上值是不可接受的。 就像输入数量的number一样,实际上不能有负数或十进制数。 但是根据TypeScript,它们是正确的。 您可以使用断言装饰器为此类无效输入保护组件:

演示地址

Did you know that if you decorate your abstract classes you do not have to pass arguments to super()? Angular will handle it for you:

您知道吗,如果您装饰抽象类,则不必将参数传递给super() ? Angular会为您处理:

演示地址

Another good case for custom decorator is some reusable processing logic. For example, in our Web Audio API library for Angular we turn declarative input bindings to imperative native commands with a strongly typed decorator:

自定义装饰器的另一个好例子是一些可重用的处理逻辑。 例如,在我们的Angular Web Audio API库中,我们将声明性输入绑定转换为具有强类型装饰器的命令性本机命令:

You can read about this library in detail here

您可以在此处详细了解该库

4. Angular的DI为王! 用它。 然后再使用它! (4. Angular’s DI is king! Use it. Then use it more!)

Dependency Injection is part of the reason Angular is such a powerful framework. Arguably it is THE reason. Too often it is not used to its full potential.

依赖注入是Angular如此强大的框架的部分原因。 可以说,这什么原因。 很多时候,它并没有充分发挥其潜力。

Head over to this dedicated article about DI we wrote to deepen you knowledge about it

转至我们撰写的有关DI的这篇专门文章,以加深您对DI的了解

RxJS (RxJS)

When it comes to practical advises, I mentioned before to watch out for memory leaks in your RxJS streams. Mainly this means: if you manually subscribe to a stream you need to unsubscribe yourself. An idiomatic solution in Angular would be to encapsulate this logic into a service:

当涉及到实用建议时,我之前提到过要提防RxJS流中的内存泄漏。 主要是指: 如果您手动订阅流,则需要取消订阅自己 。 Angular的惯用解决方案是将该逻辑封装到服务中:

演示地址

You can also create shared streams and add them to DI tree. There’s no reason to have separate requestAnimationFrame based Observables across the app. Create a token for it and reuse. You can also add zone operators discussed above to it:

您还可以创建共享流并将其添加到DI树中。 没有理由在整个应用程序中有单独的基于requestAnimationFrame的Observable。 为此创建一个令牌并重复使用。 您还可以向其添加上面讨论的区域运算符:

演示地址

代币 (Tokens)

DI is also a good way to make your components more abstract. If you do not rely on global objects, such as window or navigator — you are ready for Angular Universal which renders you app on the server side. As you know, node.js does not have DOM and many of the global objects we are used to. It is also much easier to test such code because dependencies are effortlessly mocked. It is not difficult at all to tokenize these objects. We can use factories when we define injection token and top level injector is available to us. Using built-in DOCUMENT it takes just a few lines to create WINDOW token:

DI也是使组件更抽象的好方法。 如果您不依赖于诸如windownavigator类的全局对象,则可以使用Angular Universal,它将在服务器端呈现您的应用程序。 如您所知,node.js没有DOM以及我们习惯使用的许多全局对象。 测试此类代码也容易得多,因为可以轻松模拟依赖关系。 标记这些对象并不难。 当我们定义注入令牌并且顶级注入器对我们可用时,我们可以使用工厂。 使用内置的DOCUMENT ,只需几行即可创建WINDOW令牌:

演示地址

To save time, use this open-source library where we already created some of those tokens. There’s also its Angular Universal counterpart with mocks. Feel free to request other tokens to be added!

为了节省时间,请使用此开源库 ,我们已经在其中创建了一些令牌。 还有带有模拟功能的Angular Universal 。 随时要求添加其他令牌 !

Tokens and factories are very powerful tools. Combined with hierarchical nature of dependency injection they can help you make your app very modular. Read more about clever use of providers in this article.

令牌和工厂是非常强大的工具。 结合依赖注入的分层特性,它们可以帮助您使应用程序具有高度模块化的特性。 在本文中了解有关巧妙使用提供程序的更多信息。

5.把皇帝扔到深渊。 像维达一样。 (5. Throw emperor down the abyss. Like Vader.)

Angular with its template bindings and decorators clearly pushes us to write declarative code. I’ve mentioned this approach above. I will not get into discussion of benefits it has over imperative code here. Instead I’ll give you a solid advice: write declarative code. When you get used to it, you’d appreciate it.

带有模板绑定和装饰器的Angular显然促使我们编写声明性代码。 我已经在上面提到了这种方法。 我不会在这里讨论它比命令式代码具有的好处。 相反,我会给您一个可靠的建议: 编写声明性代码 。 当您习惯了它之后,您将不胜感激。

Imperative approach is not how we do things ‘round here
强制性方法不是我们在这里所做的事情

吸气剂 (Getters)

What does it mean to write declarative code? First of all, try to use ngOnChanges as rare as you can. It’s a poorly typed side-effect which is really only needed if you must perform an action upon multiple inputs change. On a single one a setter is a more streamlined solution. And if instead of action you wanted to update some internal state, think if you can remove that manual state and replace it with calculated getter.

编写声明性代码是什么意思? 首先,尝试尽可能少地使用ngOnChanges 。 这是一个不良类型的副作用,实际上只有在必须对多个输入更改进行操作时才需要。 在一个单一的设置者是一个更简化的解决方案。 并且,如果您不想更新某些内部状态,而不是采取行动,请考虑是否可以删除该手动状态并将其替换为计算出的getter

Performance and getters is a subject for a separate article which I hope to get to writing soon. For now, just take a rule of thumb to not create new arrays or objects in getters. If you need to calculate a new object, use memoization techniques like pipes, for example.

性能和吸气剂是另一篇文章的主题,我希望尽快撰写。 现在,只需凭经验就不会在吸气剂中创建新的数组或对象。 如果需要计算新对象,请使用记忆技术,例如管道。

演示地址

Here’s a good case for a setter which I’ve omitted for the brevity of the example (but was reminded of by an attentive follower).

这对于二传手来说是个好例子,为简洁起见,我已经省略了它(但细心的追随者会提醒我)。

模板参考变量 (Template reference variables)

Instead of manually requesting elements for the view, Angular has @ViewChild decorator. Quite often though, you don’t really need it if you can enclose logic in the template:

Angular具有@ViewChild装饰器,而不是手动为视图请求元素。 不过,如果可以将逻辑包含在模板中,则通常并不需要它:

<input #input><button (click)="onClick(input)">Focus</button>

Here we pass template reference variable directly to the method where we need it. This makes our component code clear. Think of it as sort of a closure in a template. But what do we do if we need a DOM element of an underlying component? We could have @ViewChild(MyComponent, {read: ElementRef} but we can do this without decorator if we create a directive with exportAs:

在这里,我们将模板引用变量直接传递给需要它的方法。 这使我们的组件代码清晰。 可以将其视为模板中的闭包 。 但是,如果我们需要基础组件的DOM元素怎么办? 我们可以有@ViewChild(MyComponent, {read: ElementRef}但如果我们使用exportAs创建指令,则可以在没有装饰器的情况下完成此exportAs

演示地址

动态内容 (Dynamic content)

People often use ComponentFactoryResolver to create dynamic components imperatively. Why, if there is ngComponentOutlet directive? Because this way you have access to the instance and can pass some data to it. A proper way to solve this issue is, once again, dependency injection. ngComponentOutlet allows you to pass custom Injector which you can create with data provided through token.

人们经常使用ComponentFactoryResolver强制性地创建动态组件。 为什么,如果有ngComponentOutlet指令? 因为这样您就可以访问实例并可以将一些数据传递给它。 解决此问题的适当方法再次是依赖注入ngComponentOutlet允许您传递自定义Injector ,您可以使用通过令牌提供的数据来创建该Injector

In fact, to create dynamic content you have interpolation, templates and components. And there is not much difference between these approaches. You have context and your have a representation:

实际上,要创建动态内容,您需要插值模板组件 。 这些方法之间没有太大区别。 您具有上下文并且具有表示形式

演示地址

I’ve been using this content-agnostic approach to customizable components for a long time. We’ve released a tiny open-source library called ng-polymorpheus. It doesn’t do anything really, just pass content to the proper built-in Angular tool, be it ngTemplateOutlet, ngContentOutlet or simple function interpolation. Once you get used to it, there’s no going back!

我一直在使用这种与内容无关的方法来定制组件。 我们已经发布了一个名为ng-polymorpheus的小型开源库。 它实际上并没有做任何事情,只是将内容传递给适当的内置Angular工具,无论是ngTemplateOutletngContentOutlet还是简单的函数插值。 一旦习惯了,就没有回头路了!

This wraps it up for this article. Hope you would find these tips useful!

本文结束了。 希望您会发现这些提示有用!

If you like this, you can check all of our tips. We also wrote an advanced Angular handbook which we continue to develop over at angular.institute. Happy coding!

如果您愿意,可以查看我们的所有提示 。 我们还编写了高级Angular手册 ,我们将继续在angular.institute进行开发。 祝您编码愉快!

奖金 (Bonus)

A simple tip that was received unexpectedly well is Luhn algorithm in form of an Angular Validator. So if you are working on some application where users enter their credit card number, you can use this code to check its validity

angular技巧_提升Angular技能的5个技巧相关推荐

  1. angular 代码生成器_使用Angular 10构建QR代码生成器

    angular 代码生成器 In this tutorial, we'll learn how to build a QR Codes generator application using the ...

  2. 4 5区别 angular 和_初探Angular的更新机制

    了解Angular组件的渲染及更新机制在Angular应用开发中能让我们的代码更高效及优化应用性能.今天我们就来聊聊Angular的更新机制. 开发过AngularJS应用的同学可能知道一个词,脏检测 ...

  3. 幽默感七个技巧_提升幽默感的3种方法

    沃顿商学院和哈佛商学院的一份研究报告指出,有幽默感的人在职场上会被认为更自信,更有影响力,更有权威. 其实不光是在职场上,具有幽默感的人,在哪里人缘都不会太差. 那么,怎么做才能让我们变得更加幽默呢? ...

  4. 宝洁网测管道题技巧_宝洁笔试网测小技巧分享

    这里主要说三大部分,算术题.管道题和记忆题. ①算术题(digitChallenge): 所需资料:三乘表必备!!没有可以私聊我拿 注意事项:所填数字不能重复!拿真题练一下速度,清楚自己的强弱项.对我 ...

  5. 敲代码括号技巧_阅码神奇Souceinsight使用小技巧总结

    /****与SI的初遇****/ 对于大部分人第一次使用SI来说应该是对原IDE集成开发环境有很大的抱怨吧,确实我也一样,对于做嵌入式开发使用各种集成开发工具,比如说Keil,IAR等等,可能还有更加 ...

  6. python3实用编程技巧_适合Python初学者的一些编程技巧

    这篇文章主要介绍了给Python初学者的一些编程技巧,皆是基于基础的一些编程习惯建议,需要的朋友可以参考下 交换变量 x = 6 y = 5 x, y = y, x print x >>& ...

  7. idea调试debug技巧_这几个IDEA高级调试技巧,用了都说好!

    转载自: dwz.cn/zMaNp9Kf 本文将讲解的高级调试技巧如下: 条件断点 回到"上一步" 多线程调试 远程调试 临时执行表达式/修改变量的运行值 一.条件断点 循环中经常 ...

  8. 虎牙豆商赚钱技巧_如何建立赚钱会员网站的技巧 第2部分

    虎牙豆商赚钱技巧 有关如何建立赚钱会员网站的提示 (Tips on how to Build a Money-Making Membership Website) Subsequently, you ...

  9. github高级搜索技巧_分享 | 一些 GitHub 的使用小技巧

    点击上方蓝字设为星标 每周一.三.五上午 8:30 准时推送 下面开始今天的学习- 作为程序员而言,GitHub 的使用频率可能并不亚于 Google.对于 Google 我们知道一些高级搜索(比如要 ...

最新文章

  1. 那些让我唏嘘不已的嫡亲同学
  2. 1581: 统计成绩-一题简单的坑题
  3. ValueError: The QuerySet value for an exact lookup must be limited to one result using slicing.
  4. MySQL主键的理解
  5. python pandas 日期_python+pandas+时间、日期以及时间序列处理方法
  6. mysql全文搜索实现模糊查询_mysql使用全文索引实现大字段的模糊查询
  7. 查询中where和having的区别
  8. 查看类的实现类mac_自定义类加载器实现热加载
  9. em px 简单换算
  10. bzoj 1046: [HAOI2007]上升序列【dp+二分】
  11. OpenXR+Runtime:OpenXR SDK Source Code源码编译
  12. 囧从流氓同事的河蟹喜酒归来......
  13. 俄亥俄大学计算机科学系,俄亥俄大学
  14. Tensorflow (2): tf.slim库解读
  15. 守护线程daemon
  16. Weisfeiler-Leman test与WL subtree kernel
  17. Matlab交换行列
  18. 大数据给保险业带来巨大商业价值
  19. mac idea 配置 cmd+ 向上/向下 移动光标到 首/尾行
  20. php用chrome打不开,chrome打不开任何网页怎么回事_一招解决chrome打不开任何网页的方法-系统城...

热门文章

  1. idea登录gitee插件报错Unauthorized -null
  2. HTML+CSS期末网页设计前端作品(大三)
  3. 关于显卡PCIE3.0 X16 X8 X4 X1速度的测试
  4. 东京工业大学计算机毕业生去向,打开心扉 收获东京工业大学计算机专业offer
  5. Android动画特效之Animator属性动画实现
  6. 技术员 Ghost Win10 x64 装机版/纯净版 201710
  7. 数据库系统 第一部分 背景
  8. 利用计算机证明猜想,计算机科学家利用量子纠缠系统,证实44年前的一个猜想是错误的...
  9. 机试NOI:基本算法
  10. Box2D 源码编译