摘要:組件還包含數(shù)據(jù)事件的輸入與輸出,生命周期鉤子和使用單向數(shù)據(jù)流以及從父組件上獲取數(shù)據(jù)的事件對(duì)象備份。
說明:參照了Angular1.x+es2015的中文翻譯,并將個(gè)人覺得不合適、不正確的地方進(jìn)行了修改,歡迎批評(píng)指正。架構(gòu),文件結(jié)構(gòu),組件,單向數(shù)據(jù)流以及最佳實(shí)踐
來自@toddmotto團(tuán)隊(duì)的實(shí)用編碼指南
Angular 的編碼風(fēng)格以及架構(gòu)已經(jīng)使用ES2015進(jìn)行重寫,這些在AngularJS 1.5+的變化可以更好幫助您的更好的升級(jí)到Angular2.。 這份指南包括了新的單向數(shù)據(jù)流,事件委托,組件架構(gòu)和組件路由。
老版本的指南你可以在這里找到,在這里能看到最新的。
加入終極的 AngularJS 學(xué)習(xí)經(jīng)驗(yàn),完全掌握初級(jí)和高級(jí)的 AngularJS 特性,構(gòu)建更快,易于擴(kuò)展的真實(shí)應(yīng)用程序。目錄
模塊結(jié)構(gòu)
基本概念
根模塊
組件模塊
公共模塊
低級(jí)別模塊
文件命名規(guī)范
可擴(kuò)展的文件結(jié)構(gòu)
組件
基本概念
支持的屬性
控制器
當(dāng)向數(shù)據(jù)流和事件
有狀態(tài)組件
無狀態(tài)組件
路由組件
指令
基本概念
推薦的屬性
常量和類
服務(wù)
基本概念
服務(wù)的類
樣式
TypeScript 和工具
狀態(tài)管理
資源
文檔
貢獻(xiàn)
Modular architectureAngular中的每個(gè)模塊都是一個(gè)模塊組件。模塊組件是包括了組件邏輯,模板,路由和子組件的根。
Module theory模塊的設(shè)計(jì)直接反映到我們的文件夾結(jié)構(gòu),從而保證我們項(xiàng)目的可維護(hù)性和可預(yù)測(cè)性。 我們最好應(yīng)該有三個(gè)高層次的模塊:根模塊,組件模塊和常用模塊。根模塊定義用于啟動(dòng) app 和相應(yīng)的模板的基礎(chǔ)模塊。 然后導(dǎo)入我們需要依賴的組件和通用模塊。組件和通用模塊然后需要低級(jí)別的組件模塊,包含我們的組件,控制器,服務(wù),指令,過濾器和給可重復(fù)使用的功能進(jìn)行測(cè)試。
回到頂部
Root module根模塊以一個(gè)根組件開始,它定義了整個(gè)應(yīng)用程序的基本元素和路由出口,例如使用ui-router展示ui-view。
// app.component.ts export const AppComponent: angular.IComponentOptions = { template: `Hello world ` };
隨著AppComponent導(dǎo)入和使用.component("app", AppComponent)注冊(cè),一個(gè)根模塊就創(chuàng)建了。進(jìn)一步導(dǎo)入子模塊(組件和公共模塊)包括與應(yīng)用程序相關(guān)的所有組件。你可能會(huì)注意到在這里也導(dǎo)入了樣式,我們將在本直男的后面章節(jié)介紹這個(gè)。
// 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一個(gè)組件模塊是引用所有可復(fù)用組件的容器。在上面我們看到如何導(dǎo)入Components并且將他們注入到根模塊,這里給了我們一個(gè)導(dǎo)入所有應(yīng)用程序需要的組件的地方。我們要求這些模塊與其他模塊都是解耦的,因此可以很容易的移動(dòng)到其他任何應(yīng)用程序中。
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公共模塊是引用所有為應(yīng)用程序提供的特殊組件的容器,我們不希望它在其他應(yīng)用程序中使用。這可以是布局,導(dǎo)航和頁腳之類的東西。在上面我們看到如何導(dǎo)入Common并且將他們注入到根模塊,這里是給了我們一個(gè)導(dǎo)入應(yīng)用程序需要的所有的公共組件的地方。
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 modulesAlways 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.
低級(jí)別的模塊是包含每個(gè)功能塊邏輯的獨(dú)立組件。每個(gè)模塊都將定義成一個(gè)可以被導(dǎo)入較高級(jí)別的多帶帶模塊,例如一個(gè)組件或者公共模塊,如下所示。 。一定要記住每次創(chuàng)建一個(gè)新的模塊,而非引用的時(shí)候,記得給每個(gè)export中添加.name的后綴。你會(huì)注意到路由定義也在這里,我們將在隨后的部分講到它。
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 作為模塊的定義文件,這樣就可以通過目錄名導(dǎo)入模塊了。
index.ts calendar.component.ts calendar.service.ts calendar.directive.ts calendar.filter.ts calendar.spec.ts calendar.html calendar.scss
回到頂部
Scalable file structure文件目錄結(jié)構(gòu)非常重要,它有利于我們更好的擴(kuò)展和預(yù)測(cè)。下面的例子展示了模塊組件的基本架構(gòu)。
├── 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
頂級(jí)目錄僅僅包含了index.html和app/, app/目錄中則包含了我們要用到的根模塊,組件,公共模塊,以及低級(jí)別的模塊。
回到頂部
Components Component theory組件實(shí)際上就是帶有控制器的模板。他們即不是指令,也不應(yīng)該使用組件代替指令,除非你正在用控制器升級(jí)“模板指令”,它是最適合作為組件的。 組件還包含數(shù)據(jù)事件的輸入與輸出,生命周期鉤子和使用單向數(shù)據(jù)流以及從父組件上獲取數(shù)據(jù)的事件對(duì)象備份。這些都是在AngularJS 1.5及以上推出的新標(biāo)準(zhǔn)。我們創(chuàng)建的所有模板和控制器都可能是一個(gè)組件,它可能是是有狀態(tài)的,無狀態(tài)或者路由組件。你可以將“組件”看作一段完整的代碼,而不僅僅是.component()定義的對(duì)象。讓我們來探討一些組件最佳實(shí)踐和建議,然后你應(yīng)該可以明白如何通過有狀態(tài),無狀態(tài)和路由組件的概念來組織結(jié)構(gòu)。
回到頂部
Supported properties下面是一些你可能會(huì)使用到的.component()屬性 :
Property | Support |
---|---|
bindings | Yes, 僅僅使用 "@", "<", "&" |
controller | Yes |
controllerAs | Yes, 默認(rèn)是$ctrl |
require | Yes (新對(duì)象語法) |
template | Yes |
templateUrl | Yes |
transclude | Yes |
回到頂部
Controllers控制器應(yīng)該僅僅與組件一起使用,而不應(yīng)該是任何地方。如果你覺得你需要一個(gè)控制器,你真正需要的可能是一個(gè)來管理特定行的無狀態(tài)組件。
這里有一些使用Class構(gòu)建控制器的建議:
始終使用constructor來依賴注入
不要直接導(dǎo)出Class,導(dǎo)出它的名字去允許使用$inject注解
如果你需要訪問scope中的語法,請(qǐng)使用箭頭函數(shù)
另外關(guān)于箭頭函數(shù),let ctrl = this;也是可以接受的,當(dāng)然這更取決于使用場景
將所有公開的函數(shù)直接綁定到Class
適當(dāng)?shù)氖褂蒙芷阢^子,$onInit, $onChanges, $postLink 和 $onDestroy
注意:$onChanges在$onInit之前被調(diào)用,查看這里的擴(kuò)展閱讀對(duì)生命周期有進(jìn)一步的理解
在$onInit使用require去引用其他繼承的邏輯
不要使用controllerAs語法去覆蓋默認(rèn)的$ctrl別名,當(dāng)然也不要再其他地方使用controllerAs
回到頂部
One-way dataflow and Events單向數(shù)據(jù)流已經(jīng)在Angular1.5中引入了,并且重新定義了組件之間的通信。
這里有一些使用單向數(shù)據(jù)流的建議:
在組件中始終使用單向數(shù)據(jù)綁定語法<來接收數(shù)據(jù)
不要在任何地方再使用雙向綁定語法"="
有 bindings 的組件應(yīng)該使用 $onChanges 克隆單向綁定數(shù)據(jù)而阻止通過引用傳遞對(duì)象,并且更新父級(jí)數(shù)據(jù)
在父級(jí)方法中使用 $event 作為一個(gè)函數(shù)參數(shù)(查看有狀態(tài)組件的例子$ctrl.addTodo($event))
從無狀態(tài)組件傳回一個(gè) $event: {} 對(duì)象(查看無狀態(tài)組件的例子this.onAddTodo)
Bonus:使用 .value() 包裝 EventEmitter 以便遷移到 Anuglar2,避免手動(dòng)創(chuàng)一個(gè) $event 對(duì)象
為什么?這方便遷移到Angular2,并且在組件內(nèi)部保持一致性。并且可以讓狀態(tài)可預(yù)測(cè)。
回到頂部
Stateful components我們來定義下什么叫作“有狀態(tài)組件”:
本質(zhì)上通過服務(wù)于后端API通信獲取狀態(tài)
不直接改變狀態(tài)
狀態(tài)改變的時(shí)候渲染子組件
可以作為小的容器組件引用
下面的是一個(gè)狀態(tài)組件案例,它和一個(gè)低級(jí)別的模塊組件共同完成(這只是演示,為了精簡省略了一些代碼)
/* ----- 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: `` }; /* ----- 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) { } ) }
這個(gè)例子展示了一個(gè)有狀態(tài)的組件,在控制器通過服務(wù)獲取狀態(tài),然后再將它傳遞給無狀態(tài)的子組件。注意這里并沒有在模版中使例如如ng-repeat和其他指令。相反,將數(shù)據(jù)和函數(shù)代理到
回到頂部
Stateless components我們來定義下什么叫作“無狀態(tài)組件”:
使用 bindings: {} 定義輸入輸出
數(shù)據(jù)通過屬性綁定進(jìn)入組件(輸入)
數(shù)據(jù)通過事件離開組件(輸出)
狀態(tài)改變,按需傳回?cái)?shù)據(jù)(離去點(diǎn)擊和提交事件)
不關(guān)心數(shù)據(jù)來自于哪里,它是無狀態(tài)的
可高頻率復(fù)用的組件
也被稱作啞巴或者展示性組件
下面是一個(gè)無狀態(tài)組件的例子 (我們使用
/* ----- todo/todo-form/todo-form.component.ts ----- */ import { TodoFormController } from "./todo-form.controller"; export const TodoFormComponent: angular.IComponentOptions = { bindings: { todo: "<", onAddTodo: "&" }, controller: TodoFormController, template: `` }; /* ----- 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;
請(qǐng)注意
回到頂部
Routed components我們來定義下什么叫作“路由組件”:
它本質(zhì)上是一個(gè)具有路由定義的有狀態(tài)組件
沒有 router.ts 文件
我們使用路由組件去定義他們自己的路由邏輯
數(shù)據(jù)通過路由 resolve “輸入” 組件(可選,依然可以在控制器中使用服務(wù)調(diào)用)
在這個(gè)例子中,我們將利用已經(jīng)存在的
/* ----- todo/todo.component.ts ----- */ import { TodoController } from "./todo.controller"; export const TodoComponent: angular.IComponentOptions = { bindings: { todoData: "<" }, controller: TodoController, template: `` }; /* ----- 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指令給了我們 template ,scope 綁定 ,bindToController,link 和許多其他的事情。使用這些我們應(yīng)該慎重考慮現(xiàn)在的 .component()。指令不應(yīng)該再聲明模板和控制器了,或者通過綁定接收數(shù)據(jù)。指令應(yīng)該僅僅是為了裝飾DOM使用。這樣,使用 .component() 創(chuàng)建就意味著擴(kuò)展現(xiàn)有的HTML。簡而言之,如果你需要自定義DOM事件/ APIs和邏輯,在組件里使用一個(gè)指令將其綁定到模板。如果你需要的足夠的數(shù)量的 DOM操作,$postLink 生命周期鉤子值得考慮,但是這并不是遷移所有的的DOM操作,如果可以的話,你可以使用指令來處理非Angular的事情。
下面是一些使用指令的建議:
不要使用templates、scope,bindToController 或者 controllers
指令通常使用restrict: "A"
在需要的地方使用 compile 和 link
記得在$scope.$on("$destroy", fn);中銷毀或者解綁事件處理
回到頂部
Recommended propertiesDue 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:
由于指令實(shí)際上支持了大多數(shù) .component() 的語法 (模板指令就是最原始的組件), 我建議將指令對(duì)象定義限制在這些屬性上,去避免錯(cuò)誤的使用指令:
Property | Use it? | Why |
---|---|---|
bindToController | No | 在組件中使用 bindings |
compile | Yes | 預(yù)編譯 DOM 操作/事件 |
controller | No | 使用一個(gè)組件 |
controllerAs | No | 使用一個(gè)組件 |
link functions | Yes | 對(duì)于DOM 操作/事件的前后 |
multiElement | Yes | 文檔 |
priority | Yes | 文檔 |
require | No | 使用一個(gè)組件 |
restrict | Yes | 使用 "A" 去定義一個(gè)組件 |
scope | No | 使用一個(gè)組件 |
template | No | 使用一個(gè)組件 |
templateNamespace | Yes (if you must) | 文檔 |
templateUrl | No | 使用一個(gè)組件 |
transclude | No | 使用一個(gè)組件 |
回到頂部
Constants or Classes這里有使用 TypeScript 和 directives 實(shí)現(xiàn)的幾種方式,不管是使用箭頭函數(shù)還是更簡單的復(fù)制,或者使用 TypeScript 的 Class。選擇最適合你或者你團(tuán)隊(duì)的,Angular2中使用的是Class。
下面是使用箭頭函數(shù)表達(dá)式使用常量的例子() => ({}),返回一個(gè)對(duì)象字面量(注意與使用.directive()的不同):
/* ----- todo/todo-autofocus.directive.ts ----- */ import angular from "angular"; export const TodoAutoFocus = ($timeout: angular.ITimeoutService) => ({ 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 (注意在注冊(cè)指令的時(shí)候手動(dòng)調(diào)用new TodoAutoFocus)去創(chuàng)建一個(gè)新對(duì)象:
/* ----- 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服務(wù)本質(zhì)上是包含業(yè)務(wù)邏輯的容器,而我們的組件不應(yīng)該直接進(jìn)行請(qǐng)求。服務(wù)包含其它內(nèi)置或外部服務(wù),例如$http,我們可以隨時(shí)隨地的在應(yīng)用程序注入到組件控制器。我們?cè)陂_發(fā)服務(wù)有兩種方式,使用.service() 或者 .factory()。使用TypeScript Class,我們應(yīng)該只使用.service(),通過$inject完成依賴注入。
回到頂部
Classes for Service下面是使用 TypeScript Class 實(shí)現(xiàn)
/* ----- 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 我們現(xiàn)在可以在 *.module.js 中的 .scss文件上使用import 語句,讓 Webpack 知道在我們的樣式中包含這樣的文件。 這樣做可以使我們的組件在功能和樣式上保持分離,它還與Angular2中使用樣式的方式更加貼近。這樣做不會(huì)讓樣式像Angular2一樣隔離在某個(gè)組件上,樣式還可以廣泛應(yīng)用到我們的應(yīng)用程序上,但是它更加易于管理,并且使得我們的應(yīng)用結(jié)構(gòu)更加易于推理。
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元素,那么這些文件應(yīng)該放在根scss文件夾。例如scss/_forms.scss。這些全局的樣式可以像通常意義被@imported到根模塊(app.module.ts)。
回到頂部
TypeScript and Tooling使用Babel 編譯 TypeScript 代碼和其他 polyfills
考慮使用 TypeScript讓你的代碼遷移到Angular2
如果你想支持組件路由,使用ui-routerlatest alpha(查看Readme)
否則你將會(huì)被 template: "
考慮使用Webpack來編譯你的 TypeScript 代碼
使用ngAnnotate 來自動(dòng)注解 $inject 屬性
如何使用ngAnnotate with TypeScript
回到頂部
State management考慮在Angular1.5中使用Redux用于數(shù)據(jù)管理。
Angular Redux
回到頂部
ResourcesUnderstanding the .component() method
Using "require" with $onInit
Understanding all the lifecycle hooks, $onInit, $onChange, $postLink, $onDestroy
Using "resolve" in routes
Redux and Angular state management
回到頂部
DocumentationFor anything else, including API reference, check the Angular documentation.
ContributingOpen 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倉庫 準(zhǔn)備持續(xù)翻譯一些文章,方便的話給個(gè)star!謝謝~
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/95450.html
摘要:他們即不是指令,也不應(yīng)該使用組件代替指令,除非你正在用控制器升級(jí)模板指令,組件還包含數(shù)據(jù)事件的輸入與輸出,生命周期鉤子和使用單向數(shù)據(jù)流以及從父組件上獲取數(shù)據(jù)的事件對(duì)象。 showImg(https://segmentfault.com/img/bVynsJ); 關(guān)鍵詞 架構(gòu), 文件結(jié)構(gòu), 組件, 單向數(shù)據(jù)流以及最佳實(shí)踐 來自 @toddmotto 團(tuán)隊(duì)的編碼指南 Angular 的編碼...
摘要:技術(shù)棧概述大名,顧名思義是在年月正式發(fā)布的一套標(biāo)準(zhǔn)。小名,意為第六次變更。本項(xiàng)目,選擇的是的推薦配置,唯一注意的是全局變量中把的關(guān)鍵詞加上。項(xiàng)目結(jié)構(gòu)公共組件目錄,放一些二次封裝的等等片段式的。項(xiàng)目的公用樣式目錄。 技術(shù)棧概述 ES2015(ES6) 大名ES2015,顧名思義是 ECMAScript 在2015年6月正式發(fā)布的一套標(biāo)準(zhǔn)。小名ES6,意為ECMAScript第六次變更。(...
摘要:三的洋蔥模型這里簡單講講在中是如何分層的,也就是說請(qǐng)求到達(dá)服務(wù)端后如何層層處理,直到響應(yīng)請(qǐng)求并將結(jié)果返回客戶端。從而使得端支持跨域等。 ??最近已經(jīng)使用過一段時(shí)間的nestjs,讓人寫著有一種java spring的感覺,nestjs可以使用express的所有中間件,此外完美的支持typescript,與數(shù)據(jù)庫關(guān)系映射typeorm配合使用可以快速的編寫一個(gè)接口網(wǎng)關(guān)。本文會(huì)介紹一下作...
摘要:三的洋蔥模型這里簡單講講在中是如何分層的,也就是說請(qǐng)求到達(dá)服務(wù)端后如何層層處理,直到響應(yīng)請(qǐng)求并將結(jié)果返回客戶端。從而使得端支持跨域等。 ??最近已經(jīng)使用過一段時(shí)間的nestjs,讓人寫著有一種java spring的感覺,nestjs可以使用express的所有中間件,此外完美的支持typescript,與數(shù)據(jù)庫關(guān)系映射typeorm配合使用可以快速的編寫一個(gè)接口網(wǎng)關(guān)。本文會(huì)介紹一下作...
閱讀 3974·2021-09-27 13:35
閱讀 1121·2021-09-24 09:48
閱讀 2940·2021-09-22 15:42
閱讀 2377·2021-09-22 15:28
閱讀 3180·2019-08-30 15:43
閱讀 2645·2019-08-30 13:52
閱讀 3000·2019-08-29 12:48
閱讀 1483·2019-08-26 13:55