Angular1.x + TypeScript 編碼風格

說明:參照了Angular1.x+es2015的中文翻譯,並將我的以爲不合適、不正確的地方進行了修改,歡迎批評指正。

架構,文件結構,組件,單向數據流以及最佳實踐

來自@toddmotto團隊的實用編碼指南javascript

Angular 的編碼風格以及架構已經使用ES2015進行重寫,這些在AngularJS 1.5+的變化能夠更好幫助您的更好的升級到Angular2.。 這份指南包括了新的單向數據流,事件委託,組件架構和組件路由。css

老版本的指南你能夠在這裏找到,在這裏能看到最新的。html

加入終極的 AngularJS 學習經驗,徹底掌握初級和高級的 AngularJS 特性,構建更快,易於擴展的真實應用程序。

目錄

  1. 模塊結構java

    1. 基本概念
    2. 根模塊
    3. 組件模塊
    4. 公共模塊
    5. 低級別模塊
    6. 文件命名規範
    7. 可擴展的文件結構
  2. 組件webpack

    1. 基本概念
    2. 支持的屬性
    3. 控制器
    4. 當向數據流和事件
    5. 有狀態組件
    6. 無狀態組件
    7. 路由組件
  3. 指令git

    1. 基本概念
    2. 推薦的屬性
    3. 常量和類
  4. 服務angularjs

    1. 基本概念
    2. 服務的類
  5. 樣式
  6. TypeScript 和工具
  7. 狀態管理
  8. 資源
  9. 文檔
  10. 貢獻

Modular architecture

Angular中的每一個模塊都是一個模塊組件。模塊組件是包括了組件邏輯,模板,路由和子組件的根。es6

Module theory

模塊的設計直接反映到咱們的文件夾結構,從而保證咱們項目的可維護性和可預測性。 咱們最好應該有三個高層次的模塊:根模塊,組件模塊和經常使用模塊。根模塊定義用於啓動 app 和相應的模板的基礎模塊。 而後導入咱們須要依賴的組件和通用模塊。組件和通用模塊而後須要低級別的組件模塊,包含咱們的組件,控制器,服務,指令,過濾器和給可重複使用的功能進行測試。github

回到頂部web

Root module

根模塊以一個根組件開始,它定義了整個應用程序的基本元素和路由出口,例如使用ui-router展現ui-view

// app.component.ts
export const AppComponent: angular.IComponentOptions  = {
  template: `
    <header>
        Hello world
    </header>
    <div>
        <div ui-view></div>
    </div>
    <footer>
        Copyright MyApp 2016.
    </footer>
  `
};

隨着AppComponent導入和使用.component('app', AppComponent)註冊,一個根模塊就建立了。進一步導入子模塊(組件和公共模塊)包括與應用程序相關的全部組件。你可能會注意到在這裏也導入了樣式,咱們將在本直男的後面章節介紹這個。

// app.ts
import angular from 'angular';
import uiRouter from 'angular-ui-router';
import { AppComponent } from './app.component';
import { ComponentsModule } from './components/components.module';
import { CommonModule } from './common/common.module';
import './app.scss';

const root = angular
  .module('app', [
    ComponentsModule,
    CommonModule,
    uiRouter
  ])
  .component('app', AppComponent)
  .name;

export default root;

回到頂部

Component module

一個組件模塊是引用全部可複用組件的容器。在上面咱們看到如何導入Components而且將他們注入到根模塊,這裏給了咱們一個導入全部應用程序須要的組件的地方。咱們要求這些模塊與其餘模塊都是解耦的,所以能夠很容易的移動到其餘任何應用程序中。

import angular from 'angular';
import { CalendarModule } from './calendar/calendar.module';
import { EventsModule } from './events/events.module';

export const ComponentsModule = angular
  .module('app.components', [
    CalendarModule,
    EventsModule
  ])
  .name;

回到頂部

Common module

公共模塊是引用全部爲應用程序提供的特殊組件的容器,咱們不但願它在其餘應用程序中使用。這能夠是佈局,導航和頁腳之類的東西。在上面咱們看到如何導入Common而且將他們注入到根模塊,這裏是給了咱們一個導入應用程序須要的全部的公共組件的地方。

import angular from 'angular';
import { NavModule } from './nav/nav.module';
import { FooterModule } from './footer/footer.module';

export const CommonModule = angular
  .module('app.common', [
    NavModule,
    FooterModule
  ])
  .name;

回到頂部

Low-level modules

Always remember to add the .name suffix to each export when creating a new module, not when referencing one. You'll noticed routing definitions also exist here, we'll come onto this in later chapters in this guide.

低級別的模塊是包含每一個功能塊邏輯的獨立組件。每一個模塊都將定義成一個能夠被導入較高級別的單獨模塊,例如一個組件或者公共模塊,以下所示。 。必定要記住每次建立一個新的模塊,而非引用的時候,記得給每一個export中添加.name的後綴。你會注意到路由定義也在這裏,咱們將在隨後的部分講到它。

import angular from 'angular';
import uiRouter from 'angular-ui-router';
import { CalendarComponent } from './calendar.component';
import './calendar.scss';

export const CalendarModule = angular
  .module('calendar', [
    uiRouter
  ])
  .component('calendar', CalendarComponent)
  .config(($stateProvider: angular.ui.IStateProvider,
            $urlRouterProvider: angular.ui.IUrlRouterProvider) => {
    $stateProvider
      .state('calendar', {
        url: '/calendar',
        component: 'calendar'
      });
    $urlRouterProvider.otherwise('/');
  })
  .name;

回到頂部

File naming conventions

使用小寫並保持命名的簡潔, 使用組件名稱舉例, calendar.*.ts*, calendar-grid.*.ts - 將文件類型的名稱放到中間。使用 index.ts 做爲模塊的定義文件,這樣就能夠經過目錄名導入模塊了。

index.ts
calendar.component.ts
calendar.service.ts
calendar.directive.ts
calendar.filter.ts
calendar.spec.ts
calendar.html
calendar.scss

回到頂部

Scalable file structure

文件目錄結構很是重要,它有利於咱們更好的擴展和預測。下面的例子展現了模塊組件的基本架構。

├── app/
│   ├── components/
│   │  ├── calendar/
│   │  │  ├── index.ts
│   │  │  ├── calendar.component.ts
│   │  │  ├── calendar.service.ts
│   │  │  ├── calendar.spec.ts
│   │  │  ├── calendar.html
│   │  │  ├── calendar.scss
│   │  │  └── calendar-grid/
│   │  │     ├── index.ts
│   │  │     ├── calendar-grid.component.ts
│   │  │     ├── calendar-grid.directive.ts
│   │  │     ├── calendar-grid.filter.ts
│   │  │     ├── calendar-grid.spec.ts
│   │  │     ├── calendar-grid.html
│   │  │     └── calendar-grid.scss
│   │  ├── events/
│   │  │  ├── index.ts
│   │  │  ├── events.component.ts
│   │  │  ├── events.directive.ts
│   │  │  ├── events.service.ts
│   │  │  ├── events.spec.ts
│   │  │  ├── events.html
│   │  │  ├── events.scss
│   │  │  └── events-signup/
│   │  │     ├── index.ts
│   │  │     ├── events-signup.controller.ts
│   │  │     ├── events-signup.component.ts
│   │  │     ├── events-signup.service.ts
│   │  │     ├── events-signup.spec.ts
│   │  │     ├── events-signup.html
│   │  │     └── events-signup.scss
│   │  └── components.module.ts
│   ├── common/
│   │  ├── nav/
│   │  │     ├── index.ts
│   │  │     ├── nav.component.ts
│   │  │     ├── nav.service.ts
│   │  │     ├── nav.spec.ts
│   │  │     ├── nav.html
│   │  │     └── nav.scss
│   │  ├── footer/
│   │  │     ├── index.ts
│   │  │     ├── footer.component.ts
│   │  │     ├── footer.service.ts
│   │  │     ├── footer.spec.ts
│   │  │     ├── footer.html
│   │  │     └── footer.scss
│   │  └── index.ts
│   ├── index.ts
│   ├── app.component.ts
│   └── app.scss
└── index.html

頂級目錄僅僅包含了index.htmlapp/, app/目錄中則包含了咱們要用到的根模塊,組件,公共模塊,以及低級別的模塊。

回到頂部

Components

Component theory

組件實際上就是帶有控制器的模板。他們即不是指令,也不該該使用組件代替指令,除非你正在用控制器升級「模板指令」,它是最適合做爲組件的。 組件還包含數據事件的輸入與輸出,生命週期鉤子和使用單向數據流以及從父組件上獲取數據的事件對象備份。這些都是在AngularJS 1.5及以上推出的新標準。咱們建立的全部模板和控制器均可能是一個組件,它多是是有狀態的,無狀態或者路由組件。你能夠將「組件」看做一段完整的代碼,而不只僅是.component()定義的對象。讓咱們來探討一些組件最佳實踐和建議,而後你應該能夠明白如何經過有狀態,無狀態和路由組件的概念來組織結構。

回到頂部

Supported properties

下面是一些你可能會使用到的.component()屬性 :

Property Support
bindings Yes, 僅僅使用 '@', '<', '&'
controller Yes
controllerAs Yes, 默認是$ctrl
require Yes (新對象語法)
template Yes
templateUrl Yes
transclude Yes

回到頂部

Controllers

控制器應該僅僅與組件一塊兒使用,而不該該是任何地方。若是你以爲你須要一個控制器,你真正須要的多是一個來管理特定行的無狀態組件。

這裏有一些使用Class構建控制器的建議:

  • 始終使用constructor來依賴注入
  • 不要直接導出Class,導出它的名字去容許使用$inject註解
  • 若是你須要訪問scope中的語法,請使用箭頭函數
  • 另外關於箭頭函數,let ctrl = this;也是能夠接受的,固然這更取決於使用場景
  • 將全部公開的函數直接綁定到Class
  • 適當的使用生命週期鉤子,$onInit, $onChanges, $postLink$onDestroy

    • 注意:$onChanges$onInit以前被調用,查看這裏的擴展閱讀對生命週期有進一步的理解
  • $onInit使用require去引用其餘繼承的邏輯
  • 不要使用controllerAs語法去覆蓋默認的$ctrl別名,固然也不要再其餘地方使用controllerAs

回到頂部

One-way dataflow and Events

單向數據流已經在Angular1.5中引入了,而且從新定義了組件之間的通訊。

這裏有一些使用單向數據流的建議:

  • 在組件中始終使用單向數據綁定語法<來接收數據
  • 不要在任何地方再使用雙向綁定語法'='
  • bindings 的組件應該使用 $onChanges 克隆單向綁定數據而阻止經過引用傳遞對象,而且更新父級數據
  • 在父級方法中使用 $event 做爲一個函數參數(查看有狀態組件的例子$ctrl.addTodo($event)
  • 從無狀態組件傳回一個 $event: {} 對象(查看無狀態組件的例子this.onAddTodo

    • Bonus:使用 .value() 包裝 EventEmitter 以便遷移到 Anuglar2,避免手動創一個 $event 對象
  • 爲何?這方便遷移到Angular2,而且在組件內部保持一致性。而且可讓狀態可預測。

回到頂部

Stateful components

咱們來定義下什麼叫做「有狀態組件」:

  • 本質上經過服務於後端API通訊獲取狀態
  • 不直接改變狀態
  • 狀態改變的時候渲染子組件
  • 能夠做爲小的容器組件引用

下面的是一個狀態組件案例,它和一個低級別的模塊組件共同完成(這只是演示,爲了精簡省略了一些代碼)

/* ----- todo/todo.component.ts ----- */
import { TodoController } from './todo.controller';
import { TodoService } from './todo.service';
import { TodoItem } from '../common/model/todo';

export const TodoComponent: angular.IComponentOptions  = {
  controller: TodoController,
  template: `
    <div class="todo">
      <todo-form
        todo="$ctrl.newTodo"
        on-add-todo="$ctrl.addTodo($event);">
      <todo-list
        todos="$ctrl.todos"></todo-list>
    </div>
  `
};


/* ----- todo/todo.controller.ts ----- */
export class TodoController {
  static $inject: string[] = ['TodoService'];
  todos: TodoItem[];

  constructor(private todoService: TodoService) { }

  $onInit() {
    this.newTodo = new TodoItem('', false);
    this.todos = [];
    this.todoService.getTodos().then(response => this.todos = response);
  }
  addTodo({ todo }) {
    if (!todo) return;
    this.todos.unshift(todo);
    this.newTodo = new TodoItem('', false);
  }
}

/* ----- todo/index.ts ----- */
import angular from 'angular';
import { TodoComponent } from './todo.component';


export const TodoModule = angular
  .module('todo', [])
  .component('todo', TodoComponent)
  .name;

/* ----- todo/todo.service.ts ----- */
export class TodoService {
  static $inject: string[] = ['$http'];

  constructor(private $http: angular.IHttpService) { }

  getTodos() {
    return this.$http.get('/api/todos').then(response => response.data);
  }
}


/* ----- common/model/todo.ts ----- */
export class TodoItem {
    constructor(
        public title: string,
        public completed: boolean) { }
    )
}

這個例子展現了一個有狀態的組件,在控制器經過服務獲取狀態,而後再將它傳遞給無狀態的子組件。注意這裏並無在模版中使例如如ng-repeat和其餘指令。相反,將數據和函數代理到 <todo-form><todo-list> 這兩個無狀態的組件。

回到頂部

Stateless components

咱們來定義下什麼叫做「無狀態組件」:

  • 使用 bindings: {} 定義輸入輸出
  • 數據經過屬性綁定進入組件(輸入)
  • 數據經過事件離開組件(輸出)
  • 狀態改變,按需傳回數據(離去點擊和提交事件)
  • 不關心數據來自於哪裏,它是無狀態的
  • 可高頻率複用的組件
  • 也被稱做啞吧或者展現性組件

下面是一個無狀態組件的例子 (咱們使用 <todo-form> 做爲例子) , 使用低級別模塊定義來完成(僅僅用於演示,省略了部分代碼):

/* ----- todo/todo-form/todo-form.component.ts ----- */
import { TodoFormController } from './todo-form.controller';

export const TodoFormComponent: angular.IComponentOptions = {
  bindings: {
    todo: '<',
    onAddTodo: '&'
  },
  controller: TodoFormController,
  template: `
    <form name="todoForm" ng-submit="$ctrl.onSubmit();">
      <input type="text" ng-model="$ctrl.todo.title">
      <button type="submit">Submit</button>
    </form>
  `
};


/* ----- todo/todo-form/todo-form.controller.ts ----- */
import { EventEmitter } from '../common/event-emitter';
import { Event } from '../common/event';

export class TodoFormController {
  static $inject = ['EventEmitter'];

  constructor(private eventEmitter: EventEmitter) {}
  $onChanges(changes) {
    if (changes.todo) {
      this.todo = Object.assign({}, this.todo);
    }
  }
  onSubmit() {
    if (!this.todo.title) return;
    // with EventEmitter wrapper
    this.onAddTodo(
      eventEmitter({
        todo: this.todo
      });
    );
    // without EventEmitter wrapper
    this.onAddTodo(new Event({
        todo: this.todo
      }));
  }
}

/* ----- common/event.ts ----- */
export class Event {
    constructor(public $event: any){ }
}

/* ----- common/event-emitter.ts ----- */
import { Event } from './event';

export function EventEmitter(payload: any): Event {
    return new Event(payload);
}

/* ----- todo/todo-form/index.ts ----- */
import angular from 'angular';
import { EventEmitter } from './common/event-emitter';
import { TodoFormComponent } from './todo-form.component';

export const TodoFormModule = angular
  .module('todo.form', [])
  .component('todoForm', TodoFormComponent)
  .value('EventEmitter', EventEmitter)
  .name;

請注意 <todo-form> 組件不獲取狀態,它只是簡單的接收,它經過控制器的邏輯去改變一個對象,而後經過綁定的屬性將改變後的值傳回給父組件。 在這個例子中 $onChanges 生命週期鉤子克隆了初始的 this.todo 對象並從新賦值,這意味着父組件的數據在咱們提交表單以前不受影響,同時還要新的單向數據綁定語法'<' 。

回到頂部

Routed components

咱們來定義下什麼叫做「路由組件」:

  • 它本質上是一個具備路由定義的有狀態組件
  • 沒有 router.ts 文件
  • 咱們使用路由組件去定義他們本身的路由邏輯
  • 數據經過路由 resolve 「輸入」 組件(可選,依然能夠在控制器中使用服務調用)

在這個例子中,咱們將利用已經存在的 <todo> 組件,咱們使用路由定義和組件上的 bindings 接收數據(這裏使用ui-router的祕訣是咱們建立的reslove屬性,這個例子中todoData直接映射到了bindings)。咱們把它看做一個路由組件,由於它本質上是一個「視圖」:

/* ----- todo/todo.component.ts ----- */
import { TodoController } from './todo.controller';

export const TodoComponent: angular.IComponentOptions = {
  bindings: {
    todoData: '<'
  },
  controller: TodoController,
  template: `
    <div class="todo">
      <todo-form
        todo="$ctrl.newTodo"
        on-add-todo="$ctrl.addTodo($event);">
      <todo-list
        todos="$ctrl.todos"></todo-list>
    </div>
  `
};

/* ----- todo/todo.controller.ts ----- */
import { TodoItem } from '../common/model/todo';

export class TodoController {
  todos: TodoItem[] = [];

  $onInit() {
    this.newTodo = new TodoItem();
  }

  $onChanges(changes) {
    if (changes.todoData) {
      this.todos = Object.assign({}, this.todoData);
    }
  }

  addTodo({ todo }) {
    if (!todo) return;
    this.todos.unshift(todo);
    this.newTodo = new TodoItem();
  }
}


/* ----- common/model/todo.ts ----- */
export class TodoItem {
    constructor(
        public title: string = '',
        public completed: boolean = false) { }
}


/* ----- todo/todo.service.ts ----- */
export class TodoService {
  static $inject: string[] = ['$http'];

  constructor(private $http: angular.IHttpService) { }

  getTodos() {
    return this.$http.get('/api/todos').then(response => response.data);
  }
}


/* ----- todo/index.ts ----- */
import angular from 'angular';
import { TodoComponent } from './todo.component';
import { TodoService } from './todo.service';

export const TodoModule = angular
  .module('todo', [])
  .component('todo', TodoComponent)
  .service('TodoService', TodoService)
  .config(($stateProvider: angular.ui.IStateProvider, $urlRouterProvider: angular.ui.IUrlRouterProvider) => {
    $stateProvider
      .state('todos', {
        url: '/todos',
        component: 'todo',
        resolve: {
          todoData: TodoService => TodoService.getTodos();
        }
      });
    $urlRouterProvider.otherwise('/');
  })
  .name;

回到頂部

Directives

Directive theory

指令給了咱們 templatescope 綁定 ,bindToControllerlink 和許多其餘的事情。使用這些咱們應該慎重考慮如今的 .component()。指令不該該再聲明模板和控制器了,或者經過綁定接收數據。指令應該僅僅是爲了裝飾DOM使用。這樣,使用 .component() 建立就意味着擴展示有的HTML。簡而言之,若是你須要自定義DOM事件/ APIs和邏輯,在組件裏使用一個指令將其綁定到模板。若是你須要的足夠的數量的 DOM操做,$postLink 生命週期鉤子值得考慮,可是這並非遷移全部的的DOM操做,若是能夠的話,你可使用指令來處理非Angular的事情。

下面是一些使用指令的建議:

  • 不要使用templates、scope,bindToController 或者 controllers
  • 指令一般使用restrict: 'A'
  • 在須要的地方使用 compilelink
  • 記得在$scope.$on('$destroy', fn);中銷燬或者解綁事件處理

回到頂部

Recommended properties

Due to the fact directives support most of what .component() does (template directives were the original component), I'm recommending limiting your directive Object definitions to only these properties, to avoid using directives incorrectly:

因爲指令實際上支持了大多數 .component() 的語法 (模板指令就是最原始的組件), 我建議將指令對象定義限制在這些屬性上,去避免錯誤的使用指令:

Property Use it? Why
bindToController No 在組件中使用 bindings
compile Yes 預編譯 DOM 操做/事件
controller No 使用一個組件
controllerAs No 使用一個組件
link functions Yes 對於DOM 操做/事件的先後
multiElement Yes 文檔
priority Yes 文檔
require No 使用一個組件
restrict Yes 使用 'A' 去定義一個組件
scope No 使用一個組件
template No 使用一個組件
templateNamespace Yes (if you must) 文檔
templateUrl No 使用一個組件
transclude No 使用一個組件

回到頂部

Constants or Classes

這裏有使用 TypeScript 和 directives 實現的幾種方式,不論是使用箭頭函數仍是更簡單的複製,或者使用 TypeScript 的 Class。選擇最適合你或者你團隊的,Angular2中使用的是Class

下面是使用箭頭函數表達式使用常量的例子() => ({}),返回一個對象字面量(注意與使用.directive()的不一樣):

/* ----- todo/todo-autofocus.directive.ts ----- */
import angular from 'angular';

export const TodoAutoFocus = ($timeout: angular.ITimeoutService) => (<angular.IDirective> {
  restrict: 'A',
  link($scope, $element, $attrs) {
    $scope.$watch($attrs.todoAutofocus, (newValue, oldValue) => {
      if (!newValue) {
        return;
      }
      $timeout(() => $element[0].focus());
    });
  }
});

TodoAutoFocus.$inject = ['$timeout'];

/* ----- todo/index.ts ----- */
import angular from 'angular';
import { TodoComponent } from './todo.component';
import { TodoAutofocus } from './todo-autofocus.directive';

export const TodoModule = angular
  .module('todo', [])
  .component('todo', TodoComponent)
  .directive('todoAutofocus', TodoAutoFocus)
  .name;

或者使用 TypeScript Class (注意在註冊指令的時候手動調用new TodoAutoFocus)去建立一個新對象:

/* ----- todo/todo-autofocus.directive.ts ----- */
import angular from 'angular';

export class TodoAutoFocus implements angular.IDirective {
  static $inject: string[] = ['$timeout'];
  restrict: string;

  constructor(private $timeout: angular.ITimeoutService) {
    this.restrict = 'A';
  }

  link($scope, $element: HTMLElement, $attrs) {
    $scope.$watch($attrs.todoAutofocus, (newValue, oldValue) => {
      if (!newValue) {
        return;
      }

      $timeout(() => $element[0].focus());
    });
  }
}


/* ----- todo/index.ts ----- */
import angular from 'angular';
import { TodoComponent } from './todo.component';
import { TodoAutofocus } from './todo-autofocus.directive';

export const TodoModule = angular
  .module('todo', [])
  .component('todo', TodoComponent)
  .directive('todoAutofocus', ($timeout: angular.ITimeoutService) => new TodoAutoFocus($timeout))
  .name;

回到頂部

Services

Service theory

服務本質上是包含業務邏輯的容器,而咱們的組件不該該直接進行請求。服務包含其它內置或外部服務,例如$http,咱們能夠隨時隨地的在應用程序注入到組件控制器。咱們在開發服務有兩種方式,使用.service() 或者 .factory()。使用TypeScript Class,咱們應該只使用.service(),經過$inject完成依賴注入。

回到頂部

Classes for Service

下面是使用 TypeScript Class 實現<todo> 應用的一個例子:

/* ----- todo/todo.service.ts ----- */
export class TodoService {
  static $inject: string[] = ['$http'];

  constructor(private $http: angular.IHttpService) { }
  getTodos() {
    return this.$http.get('/api/todos').then(response => response.data);
  }
}


/* ----- todo/index.ts ----- */
import angular from 'angular';
import { TodoComponent } from './todo.component';
import { TodoService } from './todo.service';

export const todo = angular
  .module('todo', [])
  .component('todo', TodoComponent)
  .service('TodoService', TodoService)
  .name;

回到頂部

Styles

利用Webpack 咱們如今能夠在 *.module.js 中的 .scss文件上使用import 語句,讓 Webpack 知道在咱們的樣式中包含這樣的文件。 這樣作可使咱們的組件在功能和樣式上保持分離,它還與Angular2中使用樣式的方式更加貼近。這樣作不會讓樣式像Angular2同樣隔離在某個組件上,樣式還能夠普遍應用到咱們的應用程序上,可是它更加易於管理,而且使得咱們的應用結構更加易於推理。

If you have some variables or globally used styles like form input elements then these files should still be placed into the root scss folder. e.g. scss/_forms.scss. These global styles can the be @imported into your root module (app.module.js) stylesheet like you would normally do.

若是你有一些變量或者全局使用的樣式,像表單的input元素,那麼這些文件應該放在根scss文件夾。例如scss/_forms.scss。這些全局的樣式能夠像一般意義被@imported到根模塊(app.module.ts)。

回到頂部

TypeScript and Tooling

TypeScript
  • 使用Babel 編譯 TypeScript 代碼和其餘 polyfills
  • 考慮使用 TypeScript讓你的代碼遷移到Angular2
Tooling
  • 若是你想支持組件路由,使用ui-routerlatest alpha(查看Readme)

    • 不然你將會被 template: '<component>' 和 沒有 bindings 困住
  • 考慮使用Webpack來編譯你的 TypeScript 代碼
  • 使用ngAnnotate 來自動註解 $inject 屬性
  • 如何使用ngAnnotate with TypeScript

回到頂部

State management

考慮在Angular1.5中使用Redux用於數據管理。

回到頂部

Resources

回到頂部

Documentation

For anything else, including API reference, check the Angular documentation.

Contributing

Open an issue first to discuss potential changes/additions. Please don't open issues for questions.

License

(The MIT License)

Copyright (c) 2016 Todd Motto

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

本文github倉庫 準備持續翻譯一些文章,方便的話給個star!謝謝~
相關文章
相關標籤/搜索