摘要:組件還包含數據事件的輸入與輸出,生命周期鉤子和使用單向數據流以及從父組件上獲取數據的事件對象備份。
說明:參照了Angular1.x+es2015的中文翻譯,并將個人覺得不合適、不正確的地方進行了修改,歡迎批評指正。架構,文件結構,組件,單向數據流以及最佳實踐
來自@toddmotto團隊的實用編碼指南
Angular 的編碼風格以及架構已經使用ES2015進行重寫,這些在AngularJS 1.5+的變化可以更好幫助您的更好的升級到Angular2.。 這份指南包括了新的單向數據流,事件委托,組件架構和組件路由。
老版本的指南你可以在這里找到,在這里能看到最新的。
加入終極的 AngularJS 學習經驗,完全掌握初級和高級的 AngularJS 特性,構建更快,易于擴展的真實應用程序。目錄
模塊結構
基本概念
根模塊
組件模塊
公共模塊
低級別模塊
文件命名規范
可擴展的文件結構
組件
基本概念
支持的屬性
控制器
當向數據流和事件
有狀態組件
無狀態組件
路由組件
指令
基本概念
推薦的屬性
常量和類
服務
基本概念
服務的類
樣式
TypeScript 和工具
狀態管理
資源
文檔
貢獻
Modular architectureAngular中的每個模塊都是一個模塊組件。模塊組件是包括了組件邏輯,模板,路由和子組件的根。
Module theory模塊的設計直接反映到我們的文件夾結構,從而保證我們項目的可維護性和可預測性。 我們最好應該有三個高層次的模塊:根模塊,組件模塊和常用模塊。根模塊定義用于啟動 app 和相應的模板的基礎模塊。 然后導入我們需要依賴的組件和通用模塊。組件和通用模塊然后需要低級別的組件模塊,包含我們的組件,控制器,服務,指令,過濾器和給可重復使用的功能進行測試。
回到頂部
Root module根模塊以一個根組件開始,它定義了整個應用程序的基本元素和路由出口,例如使用ui-router展示ui-view。
// app.component.ts export const AppComponent: angular.IComponentOptions = { template: `Hello world ` };
隨著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 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.
低級別的模塊是包含每個功能塊邏輯的獨立組件。每個模塊都將定義成一個可以被導入較高級別的多帶帶模塊,例如一個組件或者公共模塊,如下所示。 。一定要記住每次創建一個新的模塊,而非引用的時候,記得給每個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.html和app/, 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: `` }; /* ----- 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和其他指令。相反,將數據和函數代理到
回到頂部
Stateless components我們來定義下什么叫作“無狀態組件”:
使用 bindings: {} 定義輸入輸出
數據通過屬性綁定進入組件(輸入)
數據通過事件離開組件(輸出)
狀態改變,按需傳回數據(離去點擊和提交事件)
不關心數據來自于哪里,它是無狀態的
可高頻率復用的組件
也被稱作啞巴或者展示性組件
下面是一個無狀態組件的例子 (我們使用
/* ----- 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;
請注意
回到頂部
Routed components我們來定義下什么叫作“路由組件”:
它本質上是一個具有路由定義的有狀態組件
沒有 router.ts 文件
我們使用路由組件去定義他們自己的路由邏輯
數據通過路由 resolve “輸入” 組件(可選,依然可以在控制器中使用服務調用)
在這個例子中,我們將利用已經存在的
/* ----- 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 和許多其他的事情。使用這些我們應該慎重考慮現在的 .component()。指令不應該再聲明模板和控制器了,或者通過綁定接收數據。指令應該僅僅是為了裝飾DOM使用。這樣,使用 .component() 創建就意味著擴展現有的HTML。簡而言之,如果你需要自定義DOM事件/ APIs和邏輯,在組件里使用一個指令將其綁定到模板。如果你需要的足夠的數量的 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:
由于指令實際上支持了大多數 .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) => ({ 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.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使用Babel 編譯 TypeScript 代碼和其他 polyfills
考慮使用 TypeScript讓你的代碼遷移到Angular2
如果你想支持組件路由,使用ui-routerlatest alpha(查看Readme)
否則你將會被 template: "
考慮使用Webpack來編譯你的 TypeScript 代碼
使用ngAnnotate 來自動注解 $inject 屬性
如何使用ngAnnotate with TypeScript
回到頂部
State management考慮在Angular1.5中使用Redux用于數據管理。
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倉庫 準備持續翻譯一些文章,方便的話給個star!謝謝~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95450.html
摘要:他們即不是指令,也不應該使用組件代替指令,除非你正在用控制器升級模板指令,組件還包含數據事件的輸入與輸出,生命周期鉤子和使用單向數據流以及從父組件上獲取數據的事件對象。 showImg(https://segmentfault.com/img/bVynsJ); 關鍵詞 架構, 文件結構, 組件, 單向數據流以及最佳實踐 來自 @toddmotto 團隊的編碼指南 Angular 的編碼...
摘要:技術棧概述大名,顧名思義是在年月正式發布的一套標準。小名,意為第六次變更。本項目,選擇的是的推薦配置,唯一注意的是全局變量中把的關鍵詞加上。項目結構公共組件目錄,放一些二次封裝的等等片段式的。項目的公用樣式目錄。 技術棧概述 ES2015(ES6) 大名ES2015,顧名思義是 ECMAScript 在2015年6月正式發布的一套標準。小名ES6,意為ECMAScript第六次變更。(...
摘要:三的洋蔥模型這里簡單講講在中是如何分層的,也就是說請求到達服務端后如何層層處理,直到響應請求并將結果返回客戶端。從而使得端支持跨域等。 ??最近已經使用過一段時間的nestjs,讓人寫著有一種java spring的感覺,nestjs可以使用express的所有中間件,此外完美的支持typescript,與數據庫關系映射typeorm配合使用可以快速的編寫一個接口網關。本文會介紹一下作...
摘要:三的洋蔥模型這里簡單講講在中是如何分層的,也就是說請求到達服務端后如何層層處理,直到響應請求并將結果返回客戶端。從而使得端支持跨域等。 ??最近已經使用過一段時間的nestjs,讓人寫著有一種java spring的感覺,nestjs可以使用express的所有中間件,此外完美的支持typescript,與數據庫關系映射typeorm配合使用可以快速的編寫一個接口網關。本文會介紹一下作...
閱讀 3872·2021-09-27 13:35
閱讀 1069·2021-09-24 09:48
閱讀 2899·2021-09-22 15:42
閱讀 2339·2021-09-22 15:28
閱讀 3145·2019-08-30 15:43
閱讀 2609·2019-08-30 13:52
閱讀 2971·2019-08-29 12:48
閱讀 1451·2019-08-26 13:55