使用 AngularJS 写前端的节奏
- 初始化代码目录, angular-seed
- 按照设计,先把首页 index.html 完成
- 在 app/js/app.js 中规划 routing
如何访问后端的 RESTful 接口
使用 ngResource 而不是使用相对原始的 http
如何更好的理解 AngularJS
通过实际交互流程来理解
- 数据录入页
- directives -> HTML 的扩展语义 (例如, ng-model, ng-controller, 以及自定义的)
- controller -> application behavior (例如,点击保存按钮对应的操作) 一般用在 div 上,已 assigns behavior to a scope
- model -> your application data (例如,输入用户名,在 js 代码里处理时,不需要通过 DOM 的方式来获取,直接通过知道的 model 名字获取即可) ngModel is directive that tells Angular to do two-way data binding.
- 数据展示页
- service -> 对后端的 RESTful api 进行操作
- 更底层的采用 $http
- filter -> 过滤需要展示的数据,也可以自定义 filter
module 与 model 不是一回事
- module -> configures the injector
- injector -> assembles your application
- model -> your application data
如何面对 angular-seed 生成的 5 个 js 文件
angular-seed 默认在 app/js 目录下产生了 5 个 js 文件。
- app.js
- controllers.js
- directives.js
- filters.js
- services.js
实际上可以写成一个文件
angular.module('myModule', []).
value('a', 123).
factory('a', function() { return 123; }).
directive('directiveName', ...).
filter('filterName', ...);
分成多个文件的原因
The reason for this breakup is that in your tests, it is often necessary to
ignore the initialization code, which tends to be difficult to test. By
putting it into a separate module it can be easily ignored in tests. The tests
can also be more focused by only loading the modules that are relevant to
tests.
通过对比这 5 个文件,可以发现
- 除了 controllers.js 其他 4 个 js 文件都是以 angular.module() 开头
- directives.js -> angular.module("myApp.directives", []).directive();
- filters.js -> angular.module("myApp.filters", []).filter();
- services.js -> angular.module("myApp.services", []).factory();
- app.js -> angular.module("myApp", ["myApp.filters", "myApp.services", "myApp.directives"]).config();
- 可见 myApp.filters, myApp.services, myApp.directives 均是自定义的名字, 若写成一个 js 文件,则可以省去这些自定义的名字
- controllers.js 则是直接 function ControllerName() {}
- 'use strict'; 每个 AngularJS 文件都采用了 JS 的 严格模式
- ControllerName.$inject = []; 用来注册 controller 的依赖关系。可省略,交由 AngularJS 自动分析。还是推荐写上。
例如,
function ControllerName($log) {}
ControllerName.$inject = ["$log"] 就是用到了 log service.
如何注册一个返回常量的 service
可以认为这是一个全局访问的常量, 在 services.js 中定义
angular.module("myApp.services", []).
value("name", "Zhongwei Sun");
辟邪剑谱中最容易被忽视的 Dependency Injection
在 filters.js 以及 directives.js 中可以看到这样的写法
directive("appVersion", ["version", function(version) {}]);
这是一个 Inline Annotation,因为匿名的回调函数不方便通过设置 $inject 属性的方 法来解决依赖,所以采用这样的语法。
再例如,如果要使用 $log
directive("appVersion", ["$log", function($log) {}]);
实际上也可以写成
directive("appVersion", function($log) {});
但是还是推荐写成第一种形式。第一种形式可以称为显式依赖注入,与之对应的就是隐式 依赖注入。隐式依赖注入可以引起的问题:
假如我们需要压缩、混淆我们的代码,这可能会导致参数名称被更改,遇到这种情况的时 候,我们还是需要使用显式声明依赖的方式。
还有一种是 module 间的依赖,例如, 我要使用 ngResource module 中的 $resource:
<script src="lib/angular/angular-resource.js"></script>
ngular.module('phonecatServices', ['ngResource']).
factory('Phone', function($resource){
return $resource('phones/:phoneId.json', {}, {
query: {method:'GET', params:{phoneId:'phones'}, isArray:true}
});
});
参考:
- https://groups.google.com/forum/#!msg/angular/UkXOVU8_3sw/Y3_gxY3DctAJ
- http://docs.angularjs.org/guide/di
- http://www.cnblogs.com/lcllao/archive/2012/10/16.html
AngularJS 这堆 js 文件的加载顺序是否有要求
AngularJS has dependency injection at its core, 小应用不需要考虑加载顺序。
directive 的命名规则
- js 里定义:directive 在定义的时候采用 ngModel 的形式
- html 里使用:ng-model
参考:
- http://blog.jdriven.com/2012/10/adding-custom-html-attributes-to-your-angularjs-web-app/
service path
return $resource("/todos/:todoId", {todoId: "@id"}
这里的 /todos 对应的即是根目录
Object # has no method 'push'
对于返回的 json 结构中包含错误码的情况,需要将 query 的 isArray 参数设置为 fasle. 否则会报上面的错误。然后在 controller 中对结果进行解析。
service action 什么时候需要加 $ 前缀
- HTTP GET "class" actions: Resource.action([parameters], [success], [error])
- non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
- non-GET instance actions: instance.$action([parameters], [success], [error])
save, remove, delete 需要加 $ 前缀,但是只是在实例化的情况下。若是直接使用类的 delete 则不需要加此前缀。
使用 Masonry + AngularJS 实现瀑布流
代码示例:
- http://jsfiddle.net/kstep/j25aj/9/
- http://jsfiddle.net/pjstarifa/uj98n/2/
AngularUI 与 Bootstrap UI 的区别
- AngularUI 是用 AngularJS 写的一些小功能组件,例如 date picker
- Bootstrap UI 则是使用 AngularJS 将 Bootstrap 的逻辑重写实现了一遍
使用 AngularJS 的输入框验证
<form class="form" novalidate>
<input type="text" required />
</form>
首先需要禁用掉浏览器自带的 form 验证,即使用 novalidate. 原因是,不同浏览器的 行为有差异。比如,chrome 对标记了 required 的输入框,在输入为空的情况下,自动 进行了提示。但是,其他浏览器就没有该行为,比如 safari. 所以需要使用统一的验证 方式。
controller getting invoked twice problem
问题,controller 里的逻辑执行了两次。
原因,controller 在 routing 以及 partial html 里定义了两次。
解决方法,去掉 partial 里的 ng-control 定义.
参考:
- https://groups.google.com/forum/#!topic/angular/yU5cvFKpdE4
AngularJS 需要注意的问题
- service 中不要定义 delete 方法, delete 由于是 js 的关键字,会造成 IE 下的不兼容,完全编译不了
- 需要进行浏览器兼容性测试(手动,自动)
- 使用 jslint 检测代码问题
- 做法是不使用 delete, 用 remove 替代
- https://groups.google.com/forum/?fromgroups=#!topic/angular/W0R6KKfv8QE
- partial view 中的 google ad 无法显示
- 放到 index.html 中
- https://groups.google.com/forum/?fromgroups=#!topic/angular/EyoYWZmsa3o
- Cross-site request forgery:跨站请求伪造 CSRF
- http://stackoverflow.com/questions/14109927/angular-js-verify-csrf-token-in-post-request
- 使用 ng-repeat 做双向绑定时,若结果集是随时更新,最好使用 array, 而不是 map
- 因为 map 默认不是双向绑定的
当N个 HTTP 请求需要顺序处理时,如何避免回调写法
- Javascript Promise 为什么这么迷人
- Understanding JavaScript Object Creation Patterns
- http://docs.angularjs.org/api/ng.$http#methods_jsonp
对 ng-view 的 PV 统计
参考:
ng-cloak
The ngCloak directive is used to prevent the Angular html template from being briefly displayed by the browser in its raw (uncompiled) form while your application is loading. Use this directive to avoid the undesirable flicker effect caused by the html template display.
ng-bind
It is preferrable to use ngBind instead of {{ expression }} when a template is momentarily displayed by the browser in its raw state before Angular compiles it. Since ngBind is an element attribute, it makes the bindings invisible to the user while the page is loading.
参考
- FAQ
- API
- 采用 AngularJS 的 app
- AngularUI
- Bootstrap UI
- AngularJS + Bootstrap 的界面设计参考
- Cheat Sheet
- Angular Pickadate
Quick Links
- BackoneJS 与 AngularJS 的比较
- 与 AngularJS 异曲同工之妙的 React
- Stop Whining About New JS Frameworks (重要的是框架背后的思想,而不是 API)
- 简单页面的 AngularJS 代码结构
- directive
- filter
- module
- controller
- Tree Table
微信关注我哦 👍
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式