AirJD 焦点
AirJD

没有录音文件
00:00/00:00
加收藏

AngularJS 进阶实践

发布者 FEer   简介 前端技术
发布于 1427709804123  浏览 11635 关键词 前端, AngularJS 
分享到

第1页

AngularJS 进阶实践

UC九游             天猪(atian25) 
http://atian25.github.io
https://github.com/atian25

第2页

AngularJS进阶
深入理解框架
摆脱思维定势
性能陷阱

第3页

摆脱思维定势 
传统前端开发思维

以JQuery为代表
以DOM为中心
关注VIEW层的变化和用户操作
「我有这样一个DOM,我想让它做XX」
新一代前端开发思维

以AngularJS为代表
以Data为中心
聚焦于数据的变更
MVW = Model + View + WhatEver
推荐阅读: http://stackoverflow.com/questions/14994391/how-do-i-think-in-angularjs-if-i-have-a-jquery-background
翻译版本: http://blog.jobbole.com/46589/

第4页

请回忆一下 ...
实现一个下拉框(三级+级联) ,需要多少代码?
实现一个表格(分页+过滤+排序+编辑),需要多少代码?
实现一个树形菜单(可缩展+级联选择),需要多少代码?
实现一个购物车(商品展示+加入/移除购物车+修改数量+实时计算总价) ,需要多少代码?

第5页

实现一个下拉框(三级+级联) ,需要多少代码?
定义下拉框A的数据源和model
定义下拉框B的数据源和model
在$watch里更新model引用
JQuery程序猿
AngularJS攻城狮
10行!
http://www.ngnice.com/showcase/#/select/cascade?utm_source=TZ
分别监控下拉框A/B/C的change事件
在事件中,取得下级的引用
查询符合上级筛选条件的下级数据
循环,更新下级的数据,更新下下级的数据
...
怎么也要百来行吧?

第6页

实现一个表格,需要多少代码?
用内置ngRepeat渲染
用内置filter过滤器过滤
用内置orderBy排序
使用自定义paging分页
无第三方组件,手写几十行代码
JQuery程序猿
AngularJS攻城狮
80行!
http://www.ngnice.com/showcase/#/table/local?utm_source=TZ
用第三方组件吧,自己写累死人
分页
过滤
排序
编辑

第7页

实现一个树形菜单,需要多少代码?
用内置ngRepeat渲染
用内置ngClass/ngShow缩展
用内置ngInclude无限嵌套
用内置ngAnimate做动画
JQuery程序猿
AngularJS攻城狮
40行!
http://www.ngnice.com/showcase/#/tree/checkbox?utm_source=TZ
用第三方组件吧,自己写累死人
级联选择
显示/隐藏

第8页

实现一个购物车,需要多少代码?
用内置ngRepeat渲染
仅仅操作数据即可
JQuery程序猿
AngularJS攻城狮
60行!
http://www.ngnice.com/showcase/#/integrated/cart?utm_source=TZ
商品展示
加入/移除购物车
修改数量
实时计算总价
又得加班了...

第9页

摆脱思维定势  - 总结
时刻以数据为中心进行思考
构思数据结构
构思操作逻辑,声明式
双向绑定VIEW,慎用逻辑
忘记「我有这么一个DOM,我想让它实现XXX」
除了Directive,其他地方决不能操作DOM
善于内置指令组合,适当写自定义指令
再看到乱操作DOM
剁手 !!!
Thinking in Angular

第10页

Look Inside – 启动过程
浏览器载入HTML,解析成DOM
加载Angular类库
DOMContentLoaded事件中开始bootstrap
寻找 ng-app, 注入服务
编译DOM并链接到对于的scope数据

第11页

Look Inside – 执行期
浏览器等待用户事件触发(用户交互,定时器,网络事件…)
浏览器执行事件回调,进入Javascript上下文
Angular在$apply中接管了JS的执行部分
Angular进入$digest循环
Angular进行脏数据检查
批量更新DOM,$digest结束
浏览器开始渲染

第12页

Look Inside – 执行期示例
编译期
Angular解析Directive: input[text]
解析ng-model并为input绑定key事件
为{{vm.name}}建立$watch表达式,进行监听

执行期
用户在input输入按键,触发了浏览器的key事件
事件回调, 进入Javascript上下文
angular接管,在$apply中修改scope的name取值
触发$digest流程
脏数据检测,发现$watch列表中的name值变更
通知对应的处理函数, 更新DOM
Angular退出执行上下文,退出Javascript的事件处理函数

第13页

Look Inside – Other
脏数据检查 != 轮询检查更新
https://docs.angularjs.org/guide/concepts
http://angular-tips.com/blog/2013/08/watch-how-the-apply-runs-a-digest/
https://github.com/angular/angular.js/wiki/Understanding-Scopes

第14页

性能优化
提速 $digest cycle
尽少的触发$digest
尽快的执行$digest
优化ngRepeat
限制列表个数(filter/page)
ngInfiniteScroll
单向绑定
不能超过2000个双向绑定
BindOnce插件
内建支持(1.3.x+)
慎用filter和事件
更多参见:http://atian25.github.io/2014/05/09/angular-performace/

第15页

Some Tips - $apply的那些事
永远忘不掉你:「Error: $apply already in progress」
反模式: if (!$scope.$$phase) $scope.$apply();
理解$apply的场景
需要使用它的场景,很少很少:
Directive里面的element.bind
WebSocket.on 事件
第三方插件修改DOM或数据后
Workaround:使用$timeout(fn, 0);
https://github.com/angular/angular.js/wiki/When-to-use-$scope.$apply()
http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

第16页

Some Tips – 原型链的坑
理解Scope原型链
https://github.com/angular/angular.js/wiki/Understanding-Scopes

使用controllerAs语法糖
http://www.cnblogs.com/whitewolf/p/3493362.html

ngModel必须有「 . 」
避免原型链继承的坑
即不能直接赋值为$scope上的基本类型
需包含一个点,即“userInfo.name"

第17页

Some Tips – 装饰模式
使用场景:需要对原生/第三方的Service/Directive进行修改时
http://briantford.com/blog/angular-hacking-core
示例:http://plnkr.co/edit/cLUSw27TuB0iFx6er5l2?p=preview

第18页

Some Tips – 动态加载
动态加载controller/service/…
主要原理:
在config期保存$controllerProvider/$provide等引用
监听ngRoute的$routeChangeStart事件
利用route的resolve去动态加载
https://github.com/atian25/angular-lazyload

动态加载module
hack module的加载机制
https://github.com/ocombe/ocLazyLoad

第19页

Some Tips – ngInclude作用域
常见需求: 同一个页面include多个模板,但需要不同的model
分析:
Template中的变量名称一样,但在父模板中要用不同的model
故需要有多级scope,每个template关联到一个scope
支持文件格式:*.pdf
上传最后阶段需要进行在线转换,可能需要1~2分钟,请耐心等待。