路由

最后更新于:2022-04-01 01:07:54

* 在视图展示之前通过 `resolve` 解决依赖。 * 不要在 `resolve` 回调函数中直接使用RESTful调用. 将所有请求放在合适的服务中. 这样你就可以使用缓存和遵循SCP.
';

模板

最后更新于:2022-04-01 01:07:52

* 使用 `ng-bind` 或者 `ng-cloak` 而非简单的 `{{ }}` 以防止页面渲染时的闪烁。 * 避免在模板中使用复杂的代码。 * 当需要动态设置 [](https://github.com/mgechev/angularjs-style-guide/blob/master/README-zh-cn.md) 的 `src` 时使用 `ng-src` 而非 `src` 中嵌套 `{{}}` 的模板。 * 当需要动态设置的 `href` 时使用 `ng-href` 而非 `href` 中嵌套 `{{ }}` 的模板。 * 通过对象参数和 scope 变量作为值来使用 `ng-style` 指令,而非将 scope 变量作为字符串通过 `{{ }}` 用于 `style`属性。 ~~~ <script> ... $scope.divStyle = { width: 200, position: 'relative' }; ... </script> <div ng-style="divStyle">my beautifully styled div which will work in IE</div>; ~~~
';

服务

最后更新于:2022-04-01 01:07:49

* 用驼峰法命名服务(大写或小写开头)。 * 将业务逻辑封装为服务。 * 将业务逻辑封装成 `service` 而非 `factory` * 可以使用 `$cacheFactory` 进行会话级别的缓存。这应该用于缓存请求或复杂运算的结果。
';

过滤器

最后更新于:2022-04-01 01:07:47

* 使用小写字母开头的驼峰法命名过滤器 * 尽可能使过滤器精简。过滤器在 `$digest` loop 中被频繁调用,过于复杂的运算将使得整个应用缓慢。 * 在过滤器中只做一件事. 更加复杂的操作可以用pipe来实现.
';

指令

最后更新于:2022-04-01 01:07:45

* 使用小写字母开头的驼峰法命名指令。 * 在 link function 中使用 `scope` 而非 `$scope`。在 compile 中, 你已经定义参数的 post/pre link functions 将在函数被执行时传递, 你无法通过依赖注入改变他们。这种方式同样应用在 AngularJS 项目中。 * 为你的指令添加自定义前缀以免与第三方指令冲突。 * 不要使用 `ng` 或 `ui` 前缀,因为这些备用于 AngularJS 和 AngularJS UI。 * DOM 操作只通过指令完成。 * 为你开发的可复用组件创建独立作用域。 * 将指令当属性和元素而不是评论和类来使用。这会使你的代码可读性更高. * 使用 `scope.$on('$destroy', fn)` 来清除. 这点在使用第三方指令的时候特别有用. * 不要忘记使用 `$sce` 当你处理不可信的资料时.
';

控制器

最后更新于:2022-04-01 01:07:42

* 不要在控制器里操作 DOM。通过指令完成。 * 通过控制器完成的功能命名控制器 (如:购物卡,主页,控制板),并以字符串`Ctrl`结尾。控制器采用驼峰命名法 (`HomePageCtrl`, `ShoppingCartCtrl`, `AdminPanelCtrl`, etc.). * 控制器不应该在全局中定义 (尽管 AngularJS 允许,但污染全局空间是个糟糕的实践)。 * 使用一下语法定义控制器: ~~~ function MyCtrl(dependency1, dependency2, ..., dependencyn) { // ... } module.controller('MyCtrl', MyCtrl); ~~~ 使用这种定义方式可以最大的避免问题。你可以使用工具自动生成数组定义,如:[ng-annotate](https://github.com/olov/ng-annotate) (and grunt task [grunt-ng-annotate](https://github.com/mzgol/grunt-ng-annotate)). * 使用控制器依赖的原名。这将提高代码的可读性: ~~~ function MyCtrl(s) { // ... } module.controller('MyCtrl', ['$scope', MyCtrl]); ~~~ 下面的代码更易理解 ~~~ function MyCtrl($scope) { // ... } module.controller('MyCtrl', ['$scope', MyCtrl]); ~~~ 对于包含大量代码的需要上下滚动的文件尤其适用。这可能使你忘记某一变量是对应哪一个依赖。 * 尽可能的精简控制器。将通用函数抽象为独立的服务。 * 通过方法引用进行跨控制器通讯 (通常是子控制器与父控制器通讯) 或者 `$emit`, `$broadcast` 及 `$on` 方法。发送或广播的消息应该限定在最小的作用域。 * 制定一个通过 `$emit`, `$broadcast` 发送的消息列表并且仔细的管理以防命名冲突和bug。 * 在需要格式化数据时将格式化逻辑封装成 [过滤器](https://github.com/mgechev/angularjs-style-guide/blob/master/README-zh-cn.md#filters) 并将其声明为依赖: ~~~ function myFormat() { return function () { // ... }; } module.filter('myFormat', myFormat); function MyCtrl($scope, myFormatFilter) { // ... } module.controller('MyCtrl', MyCtrl); ~~~ * 当内嵌的控制器 使用 "内嵌 scoping" ( `controllerAs` 语法): **app.js** ~~~ module.config(function ($routeProvider) { $routeProvider .when('/route', { templateUrl: 'partials/template.html', controller: 'HomeCtrl', controllerAs: 'home' }); }); ~~~ **HomeCtrl** ~~~ function HomeCtrl() { this.bindingValue = 42; } ~~~ **template.html** ~~~ <div ng-bind="home.bindingValue"></div> ~~~
';

模块

最后更新于:2022-04-01 01:07:40

有两种常见的组织模块的方式: 1. 按照功能 2. 按照组件类型 当前并无太大差别,但前者更加清晰。同时,如果 lazy-loading modules 被实现的话 (当前并未列入 AngularJS 的路线图),他将改善应用的性能。
';

其它

最后更新于:2022-04-01 01:07:38

* 使用: * `$timeout` 替代 `setTimeout` * `$interval` instead of `setInterval` * `$window` 替代 `window` * `$document` 替代 `document` * `$http` 替代 `$.ajax` 这将使你更易于在测试时处理代码异常 (例如:你在 `setTimeout` 中忘记 `$scope.$apply`) 使用如下工具自动化你的工作流 * [Yeoman](http://yeoman.io/) * [Gulp](http://gulpjs.com/) * [Grunt](http://gruntjs.com/) * [Bower](http://bower.io/) * 使用 promise (`$q`) 而非回调。这将使你的代码更加优雅、直观,并且免于回调地狱。 * 尽可能使用 `$resource` 而非 `$http`。更高的抽象可以避免冗余。 * 使用AngularJS的预压缩版 (像 [ngmin](https://github.com/btford/ngmin) 或 [ng-annotate](https://github.com/olov/ng-annotate)) 避免在压缩之后出现问题。 * 不要使用全局。通过依赖注入解决所有依赖。 * 不要污染 `$scope`。仅添加与视图相关的函数和变量。 * 使用 controllers 而非 `ngInit`。只有当 `ngInit` 是 `ngRepeat`的特殊别名. 除此之外, 你应该使用 controllers 而不是`ngInit` 来初始化scope变量. * 不要使用 `$` 前缀来命名变量, 属性和方法. 这种前缀是预留给 AngularJS 来使用的. * 当使用 DI 机制来解决依赖关系, 要根据他们的类型进行排序 - AngularJS 内建的依赖要优先, 之后才是你自定义的。
';

优化 digest cycle

最后更新于:2022-04-01 01:07:36

* 只监听必要的变量(例如:在进行实时通讯时,不要在每次接收到消息时触发 `$digest` loop) * 对于那些只初始化一次并不再改变的内容, 使用一次性 watcher [`bindonce`](https://github.com/Pasvaz/bindonce) 对于早期的 AngularJS 或者一次性 bindings 对于 AngularJS >=1.3.0. * 尽可能使 `$watch` 中的运算简单。在单个 `$watch` 中进行繁杂的运算将使得整个应用延缓(由于JavaScript的单线程特性,`$digest` loop 只能在单一线程进行) * 当监听集合时, 如果不是必要的话不要深度监听. 最好使用 `$watchCollection`, 对监听的表达和之前表达的估值进行浅层的检测. * 在 `$timeout` 设置第三方参数为 false 来跳过 `$digest` 循环 当没有变量被 `$timeout` 回调函数所影响. * 当面对超大不太改变的集合, [使用 immutable data structures](http://blog.mgechev.com/2015/03/02/immutability-in-angularjs-immutablejs/).
';

目录结构

最后更新于:2022-04-01 01:07:33

由于一个大型的AngularJS应用有较多组成部分,所以最好通过分层的目录结构来组织。 有两个主流的组织方式: * 按照类型优先,业务功能其次的组织方式 这种方式的目录结构看起来如下: ~~~ . ├── app │   ├── app.js │   ├── controllers │   │   ├── page1 │   │   │   ├── FirstCtrl.js │   │   │   └── SecondCtrl.js │   │   └── page2 │   │   └── ThirdCtrl.js │   ├── directives │   │   ├── page1 │   │   │   └── directive1.js │   │   └── page2 │   │   ├── directive2.js │   │   └── directive3.js │   ├── filters │   │   ├── page1 │   │   └── page2 │   └── services │   ├── CommonService.js │   ├── cache │   │   ├── Cache1.js │   │   └── Cache2.js │   └── models │   ├── Model1.js │   └── Model2.js ├── lib └── test ~~~ * 按照业务功能优先,类型其次的组织方式 如下: ~~~ . ├── app │   ├── app.js │   ├── common │   │   ├── controllers │   │   ├── directives │   │   ├── filters │   │   └── services │   ├── page1 │   │   ├── controllers │   │   │   ├── FirstCtrl.js │   │   │   └── SecondCtrl.js │   │   ├── directives │   │   │   └── directive1.js │   │   ├── filters │   │   │   ├── filter1.js │   │   │   └── filter2.js │   │   └── services │   │   ├── service1.js │   │   └── service2.js │   └── page2 │   ├── controllers │   │   └── ThirdCtrl.js │   ├── directives │   │   ├── directive2.js │   │   └── directive3.js │   ├── filters │   │   └── filter3.js │   └── services │   └── service3.js ├── lib └── test ~~~ * 当目录里有多个单词时, 使用 lisp-case 语法: ~~~ app ├── app.js └── my-complex-module    ├── controllers    ├── directives    ├── filters    └── services ~~~ * 在创建指令时,合适的做法是将相关的文件放到同一目录下 (如:模板文件, CSS/SASS 文件, JavaScript文件)。如果你在整个项目周期都选择这种组织方式, ~~~ app └── directives ├── directive1 │   ├── directive1.html │   ├── directive1.js │   └── directive1.sass └── directive2 ├── directive2.html ├── directive2.js └── directive2.sass ~~~ 那么,上述的两种目录结构均能适用。 * [ng-boilerplate](http://joshdmiller.github.io/ng-boilerplate/#/home) 采用了两种目录结构的一种更加轻量的方式。在这里,组件的单元测试与组件放置在同一目录下。在这种方式下,当改变组件时,更加容易找到对应的测试以及相关文档和用例。 ~~~ services ├── cache │   ├── cache1.js │   └── cache1.spec.js └── models ├── model1.js └── model1.spec.js ~~~ * `app.js`文件包含路由定义、配置和启动说明(如果需要的话) * 每一个 JavaScript 文件应该仅包含一个组件。文件名应该以组件名命名。 * 使用 Angular 项目模板,如 [Yeoman](http://yeoman.io/), [ng-boilerplate](http://joshdmiller.github.io/ng-boilerplate/#/home). 本人更倾向于第一种组织方式,因为更易于查找组件。
';

概览

最后更新于:2022-04-01 01:07:31

';

简介

最后更新于:2022-04-01 01:07:29

本风格指南的目的是展示AngularJS应用的最佳实践和风格指南。 这些最佳实践来自于: 1. AngularJS项目源码 2. 本人阅读过的源码和文章 3. 本人的实践经历 > **说明**: 这只是风格指南的草案,主要目的是通过交流以消除分歧,进而被社区广泛采纳。 在本指南中不会包含基本的JavaScript开发指南。这些基本的指南可以在下面的列表中找到: 1. [Google's JavaScript style guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml) 2. [Mozilla's JavaScript style guide](https://developer.mozilla.org/en-US/docs/Developer_Guide/Coding_Style) 3. [GitHub's JavaScript style guide](https://github.com/styleguide/javascript) 4. [Douglas Crockford's JavaScript style guide](http://javascript.crockford.com/code.html) 对于AngularJS开发,推荐 [Google's JavaScript style guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml). 在AngularJS的Github wiki中有一个相似的章节 [ProLoser](https://github.com/ProLoser), you can check it [here](https://github.com/angular/angular.js/wiki).
';