如果你动心了,接下来便是那省略的一万字……
痛点 – 团队分工与协作在前后端分离的开拓办法中,拆故事卡是个难题。
如果前后端同时事情于一张卡上,但合营不足默契或节奏不同步,就会涌现一方空转的征象。如果前后端各一张卡,又不随意马虎实现端到端验收,可能导致先做完的一方在另一个结束后还要再次返工的征象。而且,两个人都要深入理解这张卡所描述的业务细节,而这每每是不必要的。
更主要的是,BUG 最随意马虎涌如今边界处。
业务卡不像技能卡那样能跟其它卡片划出明确的边界,前后端之间一定具有千丝万缕的联系。这种联系越紧密,出 BUG 的机会也就越大。
技能架构上的寻衅,也会反响到职员架构上。我们人类不是星灵,无法做到心灵相通。因此前后端开拓者须要对互助方所拥有的知识进行很多主不雅观假设。
如果这些假设中存在缺点,又没能及时沟通来肃清它(乃至可能都意识不到这些假设的存在),那么 BUGs 就要登场了。而像业务卡这种级别的密切协作中可能隐含的假设实在太多了,除非经由永劫光的磨合,否则很难肃清,但大多数项目上可没有那么多磨合时间。
办理方案 —— 全栈式开拓职员架构
该如何办理呢?战胜上述问题的办法便是全栈式开拓。也便是说,调度职员架构去适应技能架构。
大略来说:每个人都同时写前端和后端。他不必是前端专家也不必是后端专家,但是两边都要会写。他的关注点不是技能知识,而是业务知识。他的事情目标是贯穿前后真个代价流,对单个故事进行端到端交付。
但是,要如何战胜实现中碰着的技能难题以及保障代码质量呢?那就要靠团队中的技能专家了。
总体来说,全栈式团队的职员架构便是大量全栈业务工程师 + 少量技能专家。当然,技能专家不一定要安排单独的人担当,只要技能知足哀求,也可以由某位全栈工程师兼任,只是他做操持时要留出做技能支持的韶光。
通过 Code Review、Pair 等敏捷实践,技能专家可以起到团队放大器的浸染,让全体团队的生产力翻倍。
个人事情流
作为全栈工程师,你首先要对一个业务故事进行建模,包括业务模型、视图模型、领域模型、存储模型等,建模的过程也便是你理解业务的过程。这时候要把稳多和 BA、UX、DBA 等沟通,以确保你的理解不存在方向性缺点,不要太沉迷细节,防止见木不见林。
单源建模的优点是这些模型之间很随意马虎保持同等,这无论是对前期开拓还是对后期掩护都是有帮助的。
建模完毕之后,就要开始设计前后端之间的接口了。接口是前后端分离式架构中最随意马虎开裂的地方,也是对未来的蜕变影响最大的地方之一。它很主要,但也不必小心翼翼的 —— 全栈工程师对接口变革的适应能力要强大得多。由于接口的供应方和消费方都是你,信息非常透明,不存在任何额外的假设。对不完美的接口,你可以在后续开拓过程中迭代好几个版本来把它打磨到最空想的形态,改接口将不再沉重和危险。
接口设计完之后,有两种路径,取决于界面和后台逻辑的特点。
如果对业务理解还不是很有信心,那就先用 Mock 的办法把前端写出来,然后把这个 Mock 版当做可实行的原型去跟 BA、QA,乃至客户进行实际操作演示,用可操作原型来验证你对业务的理解。对一样平常粒度的故事卡,线框图级的可操作原型常日能在半天内完成。通过原型尽早创造缺点,可以避免往后沉重的返工。而且,这是一个可蜕变原型,不是一次性原型,不会摧残浪费蹂躏掉。
如果后端很随意马虎实现(但先不必做优化事情),那么就可以不必 Mock,先初步完成后端开拓,并让前端直接对接真实的后端。先拿这个比 Mock 版原型更逼真一点的原型串起流程,然后再进行优化和打磨事情。
在全体过程中,你可以根据不同的须要,来与不同的技能专家进行 Pair,并且你终极的代码也会在例行 Code Review 中得到前端专家、后端专家、DBA、DevOps 专家等人的点评和改进,不必担心自己在单项技能上的短板影响交付。
全栈的寻衅
全栈固然美好,但也要欢迎很多寻衅,而 Angular 会帮你分担这些痛楚。
首先碰着的寻衅是措辞切换
前后端 JavaScript 全栈固然在特定场景下有效,但是在很多企业运用中是远远不足的。至少到目前为止,企业运用还紧张是 Java 的天下。本文所谈论的也都是 Java + JavaScript 的全栈。
我们都知道,Java 和 JavaScript 之间的差异就像雷锋和雷峰塔之间的差异。Java 程序员常日很难适应 JavaScript,不过现在有了更像 Java 的 TypeScript。而 Angular 便是原生基于 TypeScript 的框架,稍后我会做一个择要讲解,你会创造自己很熟习它的味道。
(图片来自:http://t.cn/RobG5nA)
其次是根本举动步伐
基于 JRE 的构建体系和基于 NodeJS 的构建体系看似差异很大,实际上却有很大程度的相似性。但前端两年一换代的猖獗迭代,以及层出不穷的新名词、新工具,仍旧难免会让后端心生恐怖。不过不用担心,Angular 替你封装了统统,你只须要装上 NodeJS 环境和 Angular CLI 就可以了。你不须要关心它封装了哪些第三方工具,至于今后的工具链怎么猖獗迭代,那都是 Angular 开拓组须要操心的事。
末了是最佳实践
前后端从表面上看差异很大 —— 前端轻灵,后庄重重。
但在我看来它们很少存在实质性的差异,更像是不同的社区文化导致的结果。而在更高的层次上看,两边的技能具有很大的相似性。无论是函数式编程还是工程化开拓,都不是某一方所特有的,而是 IT 领域的共同资产。况且,它们还一贯在相互影响,相互渗透 —— 这两年后端变得越来越轻灵,而前端变得越来越工程化。长远来看,文化合流是一定的趋势。
事实上,前后端很多精良设计和最佳实践都是殊途同归的。像 Spring 和 Angular,它们都采取了久经磨练的面向工具范式;都利用依赖注入技能进行解耦;都拥抱函数式编程;都供应了丰富的 AOP 支持等。虽然细节上各有千秋,但仅从代码上就能感想熏染到它们之间的相似性。
我该怎么办?
听完这些,你是否已经蠢蠢欲动?接下来,就跟我开始 Angular 之旅吧。
措辞 – TypeScript
Angular 利用 TypeScript 作为紧张开拓措辞。如果你还不熟习 TypeScript,那可以把它看做 Java 和 JavaScript 的稠浊体。TypeScript 是 ES6 的超集,这就意味着,任何有效的 ES6 语法都同样是有效的 TypeScript 语法。
事实上,从 Java 出发学 TypeScript,可能比从 ES5/6 学 TypeScript 还要大略一些。不过,对付 Javaer 来说,学习 TypeScript 时有一些主要的不同点要特殊把稳。
TypeScript 的类型只存在于编译期
TypeScript 的一个紧张设计约束便是要兼容 ES5/6,因此不能随意增加根本举动步伐,而像 Java 这种级别的类型支持在原生 JavaScript 中是根本不存在的。
你可以把 TypeScript 的类型看做仅仅给编译器和 IDE 用的。因此,在运行期间没有任何额外的类型信息(只有 ES5 固有的那一小部分),像 Java 那样完善的反射机制是很难实现的(可以用装饰器/表明实现,但比较繁琐)。
TypeScript 的装饰器 vs. Java 的表明
TypeScript 的装饰器和 Java 的表明在语法上很相似,但其实在语法含义上有着实质的差异。TypeScript 的装饰器是个函数,而 Java 的表明是个数据。语法上,装饰器名字后面必须带括号,不能像表明那样省略。
不过,在 Angular 中,TypeScript 装饰器的实际用场便是为类或属性添加表明而已。因此,有些文章中,包括早期的官方文档中,用的都是表明的说法。当然,往后写新文章还是都用装饰器吧。
类与接口
TypeScript 中的类和 ES6 中的类险些是一样的,和 Java 中的类也很相似。
接口则不同,我们前面说过,TypeScript 中的类型信息只存在于编译期,而接口作为“纯粹的”类型信息,也同样只存在于编译期。也便是说,在运行期间你无法判断某个工具的类是否实现了某个接口。在 Angular 中,实际上利用的是暴力探测法来判断的:查找这个接口中规定的方法(只匹配名称),如果存在,则认为实现了这个接口。
这也意味着,你就算不显式 implements 接口,但只要声明了个中的方法,Angular 也会精确的识别它。但这不是一个好习气,你该当始终显式 implements 接口,删除时也要同时删除接口声明和对应的方法。不过也不用担心,Angular 自带的 lint 工具会帮你检讨是否有忘了显式 implements 接口,多把稳提示就可以了。
接口是给编译器和 IDE 看的,这很有用。比如,我们可以在 IntelliJ/WebStorm 中声明某个类实现了一个接口,然后在这个类名上按 alt-enter ,就会涌现 “Implement interface XXX” 菜单 —— 就像 Java 中一样。事实上,一些 IDE 对 TypeScript 的支持程度已经靠近 Java 了:代码提示、重构、类型检讨、简短写法提醒等,搜罗万象。
值得把稳的是:你也可以 implement 一个类,而不仅是 extends 它,也便是说类可以在很多场景下代替接口!
Angular 风格指南提出,“考虑在做事和可声明工具(组件、指令和管道)中用类代替接口”。由于运行期间接口不存在,以是在 Angular 中不能把接口用作依赖注入的 Token,也就不能像 Java 中那样哀求注入一个接口,并期待框架帮你找出实现了这个接口的可注入工具,但类存在,因此,上述场景下要只管即便用抽象类来代替接口。
鸭子类型
为了支持 JavaScript 的动态性和遗留代码,TypeScript 的类型匹配要比 Java 宽松不少。比如,如果两个类(或接口)的属性和方法(名称、类型)都完备同等,那么纵然它们没有继续关系,也可以相互替代(但如果类有私有属性,则不能,就算两者完备一样也弗成)。表面上看这可能过于宽松了,但在实际开拓中还是很有用的,利用中要把稳打破 Java 固有思维的限定。
在 TypeScript 中还支持可选属性(name?: Type),也便是说如果两个类的差别仅仅在可选属性上,那么它们也是可以相互替代的。
字面量与匿名类型
TypeScript 在某些方面可能更符合你对 Java “该当是什么样子”的期待,至少在我看来是这样。要声明一个匿名工具、匿名数组型变量?直接写出来就好了const user = {name: 'tom', age: 20}。除此之外,它还能声明匿名类型 let user: {name: string, age: number} = ...。
当然,也不能滥用它们。对付一次性利用或暂时一次性利用的变量或类型,用字面量和匿名类型很方便,可读性也好,但是如果它要利用两次以上,那就该重构成正式的类型了。
any
TypeScript 中的 any 大致相称于 Java 中的 Object,如果你看到通篇 Object 的 Java 代码你会不会想骂街?any 也一样。不必完备禁止 any,但如果你要利用 any,请务必先想清楚自己要做什么。
void
如果你在 Java 中常常利用 void,那就遵照同样的原则用在 TypeScript 中。在 TypeScript 中,当你不声明函数的返回类型时,它会返回自动推断的类型(没有明确的 return value 语句时会推断为 undefined 类型),如果你不想返回任何值,那么请把返回类型指定为 void 来防止别人误用。
this
JavaScript 中的 this 是个奇葩。虽然这是函数式措辞中的标配,但从措辞设计上真是让人忍不住吐槽。假如能像 Groovy 那样分出 this / owner / delegate 就好了。
吐槽归吐槽,对付 Java 程序员,该怎么避免自己踩坑呢?很大略:对普通函数,任何涉及到 this 的地方都用箭头函数 ()=>,而不要用普通的 function foo(),由于前者是替你绑定好了符合直觉的 this 的;对方法,不要把任何涉及到 this 的方法当作函数指针传给别人,但可以在模板中自由利用。在 Angular 中,这两条原则可以帮你回避掉绝大部分 this 缺点。更多的细节可以先不管,随着利用履历的增加,你会逐渐弄明白这些规则的。
其它
以上这些是开拓中常碰着的把稳事变,其它的特性我就不一一列举了,请自行参考 TypeScript 的官方文档。
范式与模型MVVM
Angular 的基本编程模型是 MVVM,你可以把它看做 MVC 的一个变种。事实上,这是一个很符合直觉的模型:你看到一个页面,先在大脑中抽取出它的信息架构(属性)和操作(方法),定义好它们之间的逻辑关系和处理流程,这便是视图模型(VM)。你把它们落实到代码,变成内存工具,然后 Angular 就会帮你把它和页面(View)关联起来。你不懂怎么操作 DOM?没紧要,你只要会操作内存工具就可以了,这该当是你非常善于的吧?剩下的那些脏活儿 Angular 都会帮你搞定。
不过,Angular 关心的只是“要有” VM,至于你如何天生这个 VM,它并不会做任何假设和限定。
自由混搭与切换
你想怎么天生 VM?
像后端掌握器那样直接写在组件中?没问题!像后端那样委托给做事?没问题!
像 Redux 那样委托给单一 Store?没问题!
像 Java 8 Stream 那样用流水线天生?没问题!
自己险些不处理,完备委托给后端 API?没问题!
这么多办法各有不同的适用场景,但也不必过早担心如何选型。只要你的组件设计合理(职责分明、接口明确等),那么在这些办法之间切换,或者混用它们,都不会很难。
作为出发点,可以先直接写在组件中,然后按需重构成做事,做事中可以直接写代码,也可以实现 Redux 风格的单一 Store,或者用 RxJS 写流水线。
RxJS
在 Angular 开拓职员的发展过程中,有一个很主要的坎便是 RxJS,它的背后是 FRP(函数相应式编程)范式。不过对付 Javaer 来说,它的门槛并不高。如果你会用 RxJava / RxGroovy 等 ReactiveX 族的任何一个库,那么你险些可以不用专门再学,它们都是同一个大家族,编程范式乃至部分操作符的名称都一样,轻微比拟一下差异就可以了。如果不会,请连续往下读(以下的谈论也适用于 RxJava 等,不过我文中只用 RxJS 举例)。
RxJS 是一种 FRP(函数相应式编程)库,它同时具有函数式编程和相应式编程的优点。
如果你会用 Java 8 Stream,那么也有很多知识可以复用到这里。相对付 Java 8 Stream,RxJS 的限定轻微宽松一些,但我建议你仍旧按照 Java 那种严格的办法利用它(比如不要对流外的变量赋值)。
所谓相应式编程,我们可以把它想象成一条流水线,流水线上不断传送待加工的材料(质料、半成品、成品等),流水线上每个工序的工人卖力对传送到面前的材料进行一定的处理(做出相应),然后放回流水线,接着它就会被传送到下一个工序。
设计上,每个工序的职责都该当是明确而单一的,这样才能达到最高的效率和流水线的可定制性。
把这些观点映射到 RxJS,流水线便是 Observable(可不雅观察工具),工序便是 operator(操作符),材料便是传给每个 operator 的参数。
是不是感到很熟习?没错,它跟 MessageQueue 是一样的模型,只是运用在不同的层次而已。在编程领域,这种征象随处可见,长于创造并节制这种征象,是你作为资深程序员能实现快速跨领域学习的根本保障。
相对付 Java 8 Stream,RxJS 比较特殊的一点是它完备屏蔽了同步和异步之间的差异。也便是说,个中的 operator 不知道也不须要关心这个数据是同步传过来的还是异步传过来的。只要你遵照一些显而易见的原则,你就可以一贯用同步办法给数据,之后纵然要溘然改成异步,原有的代码也不会被毁坏。
事实上,我在 Angular 开拓中常常利用这种特性来加速开拓。比如假设我终极须要从后端 API 获取某些信息,在这个 API 开拓好之前,我可以先在前端仿照出相应结果,进行后续开拓。这时候,如果我用 Observable 的办法声明数据源,那么虽然我目前用同步的办法供应数据,但是将来我可以直接切换成 HTTP 数据源,而不用担心毁坏现有代码。
细部事理宏不雅观上的要点已经讲完了,接下来我们快速过一遍微不雅观的。我只讲要点,要想深入细节请参阅文中给出的参考资料。
Angular 模块
Angular 模块不同于 JavaScript 模块,它是一个架构级的根本举动步伐,用来对运用进行宏不雅观拆分,硬化边界,防止意外耦合。
模块的划分紧张基于业务领域的边界,而在开拓组织形式上,也要和模块划分办法相互对齐,只管即便让每个模块都有明确的卖力人。
拜会 https://angular.cn/guide/ngmodules。
路由
传统的路由功能完备是由后端供应的,但是在单页面运用中,在页面中点击 URL 时,将会首先被前端程序拦截,如果前端程序能处理这个 URL,那就会直接在前端处理,而不会向后端发送这个要求。
前端可以根据这个 URL 修正视图,给用户与后端路由一样的结果,但省去了网络交互的过程,因此会显得非常快捷。
路由是业务功能的天然边界,善用路由对付改进代码构造和可掩护性是很有帮助的。
在 Angular 中,路由还同时供应了惰性加载等特性,因此,早期对路由进行合理方案非常主要。不过也不用过于担心,Angular 中重新划分路由的代价并不高。
拜会 https://angular.cn/guide/router#appendix-emlocationstrategyem-and-browser-url-styles。
模板与视图
你可以把模板看做 JSP,紧张差异是 JSP 是后端渲染的,每次天生都须要一次网络交互,而模板是前端渲染的,在浏览器中实行模板编译成的 JS 来改变外不雅观和相应事宜。
模板语法
虽然看起来奇怪,但 [prop]、(click)、ngFor 等模板语法中的分外符号都是完备合法的 HTML 属性名,实际上,属性名中只禁用各种空缺字符、单双引号等少数几个显而易见的无效字符(正则:[^\t\n\f \/>\"大众'=])。
拜会 https://www.w3.org/TR/2011/WD-html5-20110525/syntax.html#syntax-attribute-name。
属性与……属性
由于历史缘故原由,英文的 Attribute 和 Property 都被译为属性,然而两者是截然不同的。Angular 中的常规绑定语法针对的都是 Property,只有 [attr.xxx] 绑定针对的是 Attribute。
拜会 https://angular.cn/guide/template-syntax#html-attribute-vs-dom-property。
组件与指令
你可以把组件看做后端模板中的 taglib,差异是它们运行在浏览器中而不是做事端。组件与指令在用场上的差异是,组件充当搭建界面的砖块,它的地位和 HTML 元素并无差异;而指令用于为 HTML 元素(包括组件)添加能力或改变行为。
以是,组件中不应该操纵 DOM,只该当关注视图模型,而指令卖力在模型和 DOM 之间建立联系。指令该当是单一职责的,如果须要完成多个职责,请拆成多个指令附加到同一个元素上。
做事与依赖注入
Angular 的做事与依赖注入和 Spring 中的很像,紧张的差异是 Angular 是个树状的多级注入体系,注入器树是和组件树逐一对应的,当组件要查找特定的做事时,会从该组件逐级向上查找,直到根部。
这实际上是职责链模式。当前组件找不到某个做事时,就会委托给其父节点来查找。和策略模式结合利用,组件就可以通过自己供应一个做事来更换父组件供应的做事,实现一种支持默认处理的逻辑。
拜会 https://angular.cn/guide/hierarchical-dependency-injection。
表单与验证
在前端程序中,验证紧张是为了用户友好性,而不是安全。安全是后真个事情,不能由于前端做了验证而放松。
Angular 对表单供应了非常强力的支持。如果你的运用中存在大量表单、大型表单、可复用表单或交互比较繁芜的表单,那么 Angular 的表单功能可以为你供应强大的助力。
Angular 的表单供应了不同层级的抽象,让你可以在开拓中轻松分离开显示、校验、报错平分歧的关注点。也让你可以先用文本框快速搭出一个表单,将来再逐个把这些文本框更换成自定义编辑框,而不会毁坏客户代码。
拜会 https://angular.cn/guide/user-input。
测试
Angular 对测试的支持非常全面,可以实现各个不同层次的测试。
但是不要由于拿到把这么好用的锤子就满天下敲。要根据不同的代价需求去决定测什么不测什么。
别忘了每个 Angular 的类,无论做事、组件、指令还是管道等,都是 POJO,你可以用测 POJO 的办法测试它们,得到毫秒级反馈,而且这每每会更高效。
拜会 https://angular.cn/guide/testing。但要记住:虽然 Angular 支持这么多种办法,但你不一定要用到这么多种办法。
安全
在 Angular 中,你不会无意间造成安全隐患。只要把稳一点就够了:DomSanitizer.bypassSecurityTrust 要慎用,务必确保传给它的东西不可能被攻击者定制,必要时请找安全专家推演。拜会 https://angular.cn/guide/security#sanitization-and-security-contexts。
如果你在发起 POST 等要求时收到了 403 缺点,那可能是由于后端开启了 CSRF 防护。Angular 内置了一个约定 —— 如果做事端 csrf token 的cookie名是 XSRF-TOKEN,并且能识别一个名叫 X-XSRF-TOKEN的要求头,那么它就会自动帮你完成 CSRF 验证。当然,你也可以自定义这些名称来适配后端,拜会 https://angular.cn/guide/http#configuring-custom-cookieheader-names。
跨域与反向代理
本地开拓时,前端有自己的做事器,显然无法与后端 API 做事器运行在同一个端口上,这样就导致了跨域问题。要办理跨域问题,紧张有 CORS 和反向代理这两种办法。CORS 是标准化的,但是受浏览器兼容性的影响较大;而反向代理则通过把 API “拉”到前真个同一个域下,从根本上肃清了跨域访问。
开拓时,Angular CLI 内置了对反向代理的支持;支配时,各个主流 Web 做事器都能很好地支持反向代理。
一样平常项目中建议还是优先利用反向代理的办法。
(图片来自:http://t.cn/RgsWKEJ)
杂谈你不必写 CSS
很多后端初学前端时会被卡在 CSS 上,在心里喊一句 WTF。但实际上,在团队开拓中,你可能根本不必写 CSS。
现在已经有了很多现成的 CSS 库,比如已经熟透的 Bootstrap,还有后起之秀 Material Design、Ant Design 等等。你只要能根据其表达的视觉含义,精确套用它们定义的 CSS 类就够了。只管即便不要自己手写 CSS,否则可能反倒会给将来的页面美化事情带来困扰。
选好了根本框架,并且和 UX 对齐之后,团队中只须要一个 CSS 高手就能实现所有的全局性设计规则。对付全栈工程师来说,充其量只有对当前页面中的少量元素进行定制时才须要写 CSS,况且还可以通过找人 pair 来办理偶尔碰到的难题。
全栈,让设计更大略
前后端技能各有千秋,有些事情用前端实现更大略,有些用后端实现更大略。综合考量前端技能和后端技能,每每可以产生更大略、更精良的设计。广度在业务开拓中每每比深度有用,这也是全栈工程师的上风所在。而团队中的技能专家紧张卖力深度。
分工是动态的
技能专家或全栈工程师,并不是什么名誉头衔,只是分工不同而已。
同一个项目上你可以同时担当全栈工程师和技能专家;这个项目你是全栈工程师,下一个项目上也可能专门担当技能专家。团队的协作办法永久是动态的、随需应变的。
不用担心全栈会限定你的技能深度,实际上,全栈对提高你的技能深度是有帮助的,由于很多技能的“根”都是互通的。
相信你的直觉
资深后端首先是一个资深程序员,你对付“该当如何”的期待,很可能是对的。如果你以为 Angular 该当有某项功能或某种设计,它很可能确实有。去 Stackoverflow 搜一下,找找你的答案,这是你成为高等 Angular 程序员的捷径。
万法归一
形容某人聪明时常常说“万法皆通”,实际上“万法皆通”不如“一法通而万法通”。很多技能之间的相似程度超出你的想象,这些相似的部分实在便是技能的核心。用万法归一的思路去学习总结,会给你带来真正的提高。
资料 & 学习指南学习 Angular 的最佳资料是它的官方文档,它无论是从准确、全面,还是及时性等方面都是最佳的。
它的英文文档站是 https://angular.io,中文文档站是 https://angular.cn,这是由我和其余两位社区志愿者共同翻译的,期间还得到了很多社区志愿者的支持。中文文档和英文文档至少在每个大版本都会进行一次同步翻译。虽然韶光有限导致措辞上还有粗糙之处,不过你可以相信它的技能准确度是没问题的。
阅读时,请先阅读架构概览 https://angular.cn/guide/architecture,然后阅读教程 https://angular.cn/tutorial(有履历的程序员不须要随着敲代码,如果韶光紧也可跳过),末了阅读风格指南 https://angular.cn/guide/styleguide。风格指南很主要,不用记住,但务必通读一遍,有点印象供将来查阅即可。
文档站中还供应了 API 参考手册,它供应了大略快速的站内搜索功能,须要理解哪些细节时到里面查就可以了。
其余,ng-zorro 组件库的一位开拓者还整理了一份不完备指南,包括中英文资料:https://zhuanlan.zhihu.com/p/36385830。
文/ThoughtWorks汪志成(雪狼)
原文:https://insights.thoughtworks.cn/angular-guide-for-java-developer/