Angular 2
背景
作为一个全栈工程师,前端 JS 库的使用是必备的技能。除了老牌的 jQuery,当下还有 React/Angular/Vue 这三座大山,但是我已经使用过 Angular 1 和 2,而且 Angular 作为 Google 的重要产品应该能长期开发维护。因此我选择了 Angular 2 作为前端的主力 JS 库。
Angular 2 是什么
以下为 Wiki 上的定义:
AngularJS 是一个完整的基于 JavaScript 的开源的前端网络应用框架,主要由 Google 和一个个人和组织组成的社会维护,用以处理在开发单页面应用中遇到的多个挑战。这个 JavaScript 组件补充了 Apache Cordova,这个跨国那就爱用于开发跨平台移动应用。它通过提供一个针对于客户端侧 MVC 和 MVVM 结构 ,和在丰富的网络应用中常用的组件配合,致力于简化开发和测试。AngularJS 框架通过首选读取 HTML 页面工作,该页面已经嵌入了附加的定制化的标签属性。Angular 将这些属性翻译成指令来将页面的输入或者输出部分绑定到一个被标准 JavaScript 变量代表的模型上。这些 JavaScript 变量的值可以在代码中被手动设置,或者从静态的或动态的 JSON 资源中获取。AngularJS 基于声明式编程应该用来创建用户界面和连接软件组件,同时命令时编程更适合定义一个应用的业务逻辑的理念被构建。该框架通过允许模型和视图自动同步的双向绑定,改编并扩展了传统的 HTML 来体现动态内容。作为结果,AngularJS 由于提升可测试性和性能的目标,不再强调 DOM 的操作。
AngularJS 的设计目标包括:
- 从应用逻辑中解耦 DOM 操作。通过这种方式组织代码,高耦合所产生的困难被明显影响;
- 从服务器侧解耦应用的服务器侧。该措施将允许并行工作,并允许双方的复用;
- 针对构造一个应用的过程提供一个结构:从设计 UI,到写业务逻辑,再到测试;
Angular 的出现以及解决了哪些问题
Angular 出现之前
JavaScript 是一门独立的语言,可以通过浏览器访问 DOM,通过控制被渲染成的 DOM 树,增强网页的表现力。
再来看 jQuery,以下为 Wiki 上的定义:
jQuery,说到底,是一个 DOM 操作库。DOM 是一个网页里所有元素树形结构表现,并且 jQuery 简化了查找、选择和操作这些 DOM 元素的语法。jQuery 也提供了一个事件处理的范式,超越了基本的 DOM 元素的选择和操作。在代码中的同一个地方的同一个步骤,事件赋值和事件回调函数定义就被完成了。jQuery 也力求包含其他常用的 JavaScript 功能。
总结起来,jQuery 其实就是 JavaScript 的高级封装,将常用的功能封装成高层的函数,用起来比较方面。jQuery 是库,而不是框架。相比原生的 JavaScript,jQuery的优点是用较少的代码就可以实现相同的功能,并能够更好的处理事件。但是其缺点也很明显,包括在处理页面数据的变化和一致性上需要花费大量的时间和精力,并且没有固定的开发范式,不能很好的约束开发规范和设计模式,导致代码质量参差不齐。
Angular 和 jQuery 的区别
- jQuery 是库,而 Angular 是框架。库是工具的集合,框架是开发规范;
- 思维方式。这也是我刚开始学习 Angular 感受到的最大的不同。jQuery 是很直观的思维,想修改页面上的哪里,通过 DOM 直接修改就可以。而 Angular 作为框架,则提供的固定的 MVVM 设计模式,把视图层的数据和控制器层的数据统一了起来,将数据抽象成了一个对象而不仅仅是页面上的文本;
- UI 和业务逻辑的耦合性;
Angular 2 和 Angular 1 的区别
Angular 1 的遗留问题
虽然 Angular 1 很优秀,还是有很多问题和缺点:
- MVVM 化还不够彻底。还保留有很多中间的
- 对于移动应用不够友好;
- 需要学习很多 Angular 1 的定制化标签;
- 路由功能太薄弱;
- 弱类型。当然,这个其实是 JavaScript 的问题;
Angular 2 的改变
Angular 2 的区别
- 面向移动应用和性能优化;
- 更多语言选择。通过 TypeScript 可以有效增强类型检查等功能;
- 组件化;
- 直接使用有效的 HTML DOM 属性和事件;
- 可以自主选择单向还是双向绑定;
- 路由语法;
- 绑定方式;
Angular 2 的特性
- 跨平台
- 给予 app 式的网页体验;
- 借助其他技术,构建原生移动应用;
- 结合原生操作系统的 API,创建跨平台桌面应用;
- 速度和性能
- 利用模板开发,最终产品再进行高度优化;
- 支持众多后台服务,服务端渲染首屏快速打开,SEO 优化友好;
- 用户可单独加载需要的代码;
- 生产率
- 模板语法快速构建;
- 命令行工具提升效率;
- IDE 友好;
- 完整开发过程
- 单元测试和场景测试相结合;
- 通过 API 创建动画;
- 高度的可访问性,方便各类人群;
Angular 2 常用依赖
- core-js。是针对 JavaScript 的模块标准库。包括 ECMAScript5/6/7 的一些“垫片”。意思是允许原本那些不支持 ECMAScript 特性的浏览器支持这些特性。
- rxjs。RxJS 是可观察流的异步编程 API 的 JavaScript 实现,是一种设计模式的语言实现。之前我已经在 HTTP 的请求中已经大量运用了,不过当时只是简单的语法使用,没有看到其全貌;
- zone。zone 是一个可以在异步任务之间进行持久性传递的执行过程上下文。你可以把它想象成针对 JavaScript 虚拟机的线程本地存储。这里暂时不再继续讨论,详情可以看[此文章][zone];
- reflect-metadata。也是垫片。用来加入 ECMAScript 7 的装饰器功能,并提供一个 ECMAScript 7 对装饰器元数据 的反射 API。也是 Angular 2 种的基础功能,务必要提前了解一下。[zone]: http://blog.thoughtram.io/angular/2016/01/22/understanding-zones.html
全面掌握 Angular 2 的方向
- 理解依赖注入模式;
- 理解单/双向绑定;
- 理解装饰器模式;
- 理解观察者模式;
Angular 2 的高效工具
- Angular-CLI;
- Augury;
- Codelyzer;
- Angular-seed;
详细的区别可以查阅此文章。还可以通过这个 ng-conf 大会上的视频更直观地发现 Angular 2 和 1 的区别以及当前的特性。
Angular 2 启动原理
Angular 2 在浏览器中如何引导
TODO:在此写下浏览器如何引导 Angular 的流程。
Angular 2 开发
基础开发流程
- 建立基础配置文件,例如 package.json/tsconfig.json,以及模块加载配置文件(可以采用 SystemJS 或者 Webpack );
- 建立根模块。模块是 Angular 2 RC 5 以后引入的新概念,我理解类似于 Node.js 的 npm 包管理,即把某些功能封装在独立的模块中,便于管理、方便解耦;
- 建立根组件并引入到根模块中。组件是 Angular 应用的基本构造块。每个组件都会通过与它相关的模板来控制屏幕上的一小块(视图)。根模块只是一个功能集合包,但根模块文件本身不包含任何功能,因此需要需要至少有一个根组件来提供功能。根组件表示出应用的主视图,它是所有其他视图的宿主;
- 建立 Angular 引导文件 main.ts。用于在浏览器中引导根模块;
- 定义宿主页面 index.html;
- 编译并运行应用;为什么分离模块、组件和引导文件:应用的引导过程和模块或者视图展现是相互独立的关注点。分离以后方便解耦和测试,也可以以后更换引导器。
问题
阅读官方教程中出现的问题
问题
- 开发指南 -> 架构:父组件和子组件如何做数据绑定;
-
开发指南 -> 架构:依赖注入的提供商到底是什么,和注入的依赖是什么关系。我现在的感觉是,提供商的类本身,注入的依赖是类的实例; - 开发指南 -> 用户输入:
(click)="onClick()"
,这个 click 事件在 DOM 中和绑定的 button 元素是什么关系; - 开发指南 -> 表单:
moduleId = module.id
是什么意思; -
开发指南 -> 表单:双向绑定的过程中,是什么机制使得变量能在 DOM 和组件之间来回传递,而不需要监听 keyup 等事件; - 开发指南 -> 表单:组件里面的
get diagnostic()
是什么意思。是 JavaScript 的 getter 和 setter 么。这又是什么意思; - 开发指南 -> 表单:forms.css 里的
.ng-invalid:not(form)
是什么意思; - 开发指南 -> 表单:
#name="ngModel"
这句作何解释,看了下面的解释还是不清楚,这样赋值了以后,name 是否就表示了一个表单控件呢。还有#heroForm="ngForm"
也不理解; - 开发指南 -> 依赖注入:非类依赖的那部分不是很理解,尤其是
OpaqueToken
的使用; - 开发指南 -> 模板语法:插值表达式 Interpolation 和模板表达式 Template expression 有什么区别。是不是插值表示两个花括号和里面的模板表达式这个整体呢;
-
开发指南 -> 模板语法:;[routerLink]="['/']"
这种的绑定目标到底是元素、组件还是指令的属性啊,觉得都不是 - 开发指南 -> 模板语法:使用 EventEmitter 实现自定义事件的具体应用场景是什么?具体如何使用;
- 开发指南 -> 风格指南:特性区的模块该如何定义,特性区的模块文件和路由模块文件是什么关系;
- 开发指南 -> 风格指南:风格 04-10,把可能被应用到其他特性模块使用的公共资产(如组件、指令和管道)放在 SharedModule 中,这些资产倾向于共享自己的新实例(而不是单例)。这个共享新实例和单例分别是什么意思;
- 开发指南 -> 风格指南:风格 04-11,
CoreModule
到底是什么,应该怎么使用; - 教程 -> HTTP:InMemoryDataService 中到底如何设置可以模拟数据服务中的 url 并匹配;
- 高级文档 -> 路由与导航:index.html 中设置的
<base href="/">
为什么将 app 作为根目录,index.html 和 app 目录不是平级的吗,根目录应该是 src 啊;18. 高级文档 -> HTTP 客户端:为什么 Angular 官方鼓励服务器发送数据的时候将真实数据放在 data 属性下面; - angular2-jwt:有个叫做 JwtHelper 的类,为什么不能作为供应商;
- 如何避免 angular2 本身的 selector 导致 html 原有的结构发生改变,从而影响 SEO 和 CSS 规则;
- 如何
解答
- 依赖注入的提供商可以是很多种形态,可以是类或者是值,被注入的依赖是提供商可以转换成的实例对象;
- 在开发指南 -> 表单中就有 ngModel 的双向绑定原理的解释。但是还需要深入了解属性指令是怎么回事,为什么 ngModel 指令能够影响表单的值;
- 绑定目标是指令属性;
最佳实践
- 不要在 SharedModule 中为惰性加载模块提供服务,将服务放在 CoreModule 中全局使用;