国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

使用 ES2015 開發(fā) Angular1.x 應用指南

Andrman / 3320人閱讀

摘要:他們即不是指令,也不應該使用組件代替指令,除非你正在用控制器升級模板指令,組件還包含數(shù)據(jù)事件的輸入與輸出,生命周期鉤子和使用單向數(shù)據(jù)流以及從父組件上獲取數(shù)據(jù)的事件對象。

關鍵詞 架構, 文件結構, 組件, 單向數(shù)據(jù)流以及最佳實踐

來自 @toddmotto 團隊的編碼指南

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

老版本的指南你可以在這里找到, 在這里你能看到最新的.

模塊架構

Angular 中的每一個模塊都是一個模塊組件。一個模塊組件囊括了邏輯,模版,路由和子組件。

Module 基本概念

在模塊的設計直接反映到我們的文件夾結構,從而保證我們項目的可維護性和可預測性。
我們最好應該有三個高層次的模塊:根,組件和常用模塊。根模塊定義了用于啟動App和相應的模板的基本架子。
然后,我們導入需要依賴的組件和通用模塊。組件和通用模塊然后需要低級別的組件模塊,其中包含我們的組件,控制器,服務,指令,過濾器和給可重復使用的功能進行測試。

根模塊

根模塊會啟動一個根組件,整個組件主要定義了整個應用的基本的元素和路由出口,例如使用ui-viewui-router

// app.component.js
const AppComponent = {
  template: `
    
Hello world
Copyright MyApp 2016.
` }; export default AppComponent;

我們導入AppComponent并且使用.component("app",AppComponent)完成注冊即表示一個根模塊創(chuàng)建完成。
更進一步我們會導入一些子模塊(組件和通用模塊)用于引入相關的組件。

// app.js
import angular from "angular";
import uiRouter from "angular-ui-router";
import AppComponent from "./app.component";
import Components from "./components/components";
import Common from "./common/common";

const root = angular
  .module("app", [
    Components,
    Common,
    uiRouter
  ])
  .component("app", AppComponent);

export default root;
組件模塊

一個組件模塊就是引用所有課重復使用的組件容器。上面我們可以了解我們如何導入組件和將它們注入到根模塊,
這樣我么可以有一個地方導入所有應用程序需要的組件。
我們要求這些模塊從所有其它模塊分離出來,這樣這些模塊可以應用到其它的應用程序中。

import angular from "angular";
import Calendar from "./calendar";
import Events from "./events";

const components = angular
  .module("app.components", [
    Calendar,
    Events
  ])
  .name;

export default components;
公共模塊

公共模塊為所有的應用提供一些特殊組件的引用,我們不希望它能夠在另一個應用程序中使用。比如布局,導航和頁腳。
前面我們已經知道如何導入Common并將其注入到根模塊,而這里就是我們導入所有通用組件的地方。

import angular from "angular";
import Nav from "./nav";
import Footer from "./footer";

const common = angular
  .module("app.common", [
    Nav,
    Footer
  ])
  .name;

export default common;
低級別的模塊

低層次的模塊是一些獨立的組件,它們包含邏輯和功能。這些將分別定義成模塊,被引入到較高層次模塊中,
比如一個組件或通用模塊。一定要記住每次創(chuàng)建一個新的模塊時(并非引用),記得在export中添加后綴。你會注意到路由定義也是在這里,我們將在隨后的部分講到它。

import angular from "angular";
import uiRouter from "angular-ui-router";
import CalendarComponent from "./calendar.component";

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

export default calendar;
文件命名規(guī)范

使用小寫并保持命名的簡介, 比如使用組件名稱時, e.g. calendar.*.js*, calendar-grid.*.js - 將名稱放到中間. 使用 index.js 作為模塊的定義文件 ,這樣你就可以直接通過目錄引入了。

index.js
calendar.controller.js
calendar.component.js
calendar.service.js
calendar.directive.js
calendar.filter.js
calendar.spec.js

返回目錄

易于擴展的文件結構

文件目錄結構實際上十分重要,它有利于我們更好的擴展和預測。下面的例子展示了模塊組件的基本架構。

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

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

組件 組件的基本概念

組件實際上就是帶有控制器的模板。他們即不是指令,也不應該使用組件代替指令,除非你正在用控制器升級“模板指令”,
組件還包含數(shù)據(jù)事件的輸入與輸出,生命周期鉤子和使用單向數(shù)據(jù)流以及從父組件上獲取數(shù)據(jù)的事件對象。
從父組件獲取數(shù)據(jù)備份。這些都是在Angular 1.5及以上推出的新標準。
我們創(chuàng)建的一切模板,控制器都可能是一個組件,它們可能是是有狀態(tài)的,無狀態(tài)或路由組件。
你可以把一個“部件”作為一個完整的一段代碼,而不僅僅是.component()定義的對象。
讓我們來探討一些組件最佳實踐和建議,然后你應該可以明白如何組織他們。

支持的屬性

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

Property Support
bindings Yes, 僅僅使用 "@", "<", "&"
controller Yes
controllerAs Yes, 默認 $ctrl
require Yes (new Object syntax)
template Yes
templateUrl Yes
transclude Yes
控制器

控制器應該只與組件一起使用。如果你覺得你需要一個控制器,你真正需要的可能是一個無狀態(tài)的組件來管理特定的行為。

這里有一些使用Class構建controller的建議:

始終使用 constructor 用于依賴注入;

不要直接導出 Class,導出它的名稱,并允許$inject;

如果你需訪問到 scope 里的語法,使用箭頭函數(shù);

另外關于箭頭 函數(shù), let ctrl = this; 也是可以接受的,當然這更取決于使用場景;

綁定到所有公共函數(shù)到Class上;

適當?shù)睦蒙芷诘囊恍┿^子, $onInit, $onChanges, $postLink 以及$onDestroy

注意: $onChanges$onInit之后調用的, 這里 擴展閱讀 有更深一步的講解。

$onInit使用require 以便引用繼承的邏輯;

不要覆蓋默認 $ctrl 使用controllerAs 起的別名, 當然也不要在別的地方使用 controllerAs

One-way dataflow and Events

單向數(shù)據(jù)流已經在Angular1.5中引入了,并且重新定義了組件之間的通信。

關于單向數(shù)據(jù)流的一些小建議:

在組件接受數(shù)據(jù),始終使用 單向數(shù)據(jù)綁定符號"<"

不要再使用 "="雙向的數(shù)據(jù)綁定的語法

擁有綁定的組件應該使用$ onChanges克隆單向綁定的數(shù)據(jù)阻止對象通過引用傳遞和更新原數(shù)據(jù)

使用 $event 作為一個父級方法中的的一個函數(shù)參數(shù)(參見有狀態(tài)的例子 $ctrl.addTodo($event))

傳遞一個$event: {} 從無狀態(tài)的組件中進行備份(參見無狀態(tài)的例子 this.onAddTodo).

Bonus: 使用 包裹 .value()EventEmitter 以便遷到Angular2 , 避免手動創(chuàng)建一個 $event

為什么? 這和Angular2類似并且保持組件的一致性.并且可以讓狀態(tài)可預測。

有狀態(tài)的組件

什么是“有狀態(tài)的組件”

獲取狀態(tài),通過服務與后端API通信

不直接發(fā)生狀態(tài)變化

渲染發(fā)生狀態(tài)變化的子組件

作為一個組件容器的引用

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

/* ----- todo/todo.component.js ----- */
import controller from "./todo.controller";

const TodoComponent = {
  controller,
  template: `
    
` }; export default TodoComponent; /* ----- todo/todo.controller.js ----- */ class TodoController { constructor(TodoService) { this.todoService = TodoService; } $onInit() { this.newTodo = { title: "", selected: false }; this.todos = []; this.todoService.getTodos.then(response => this.todos = response); } addTodo({ todo }) { if (!todo) return; this.todos.unshift(todo); this.newTodo = { title: "", selected: false }; } } TodoController.$inject = ["TodoService"]; export default TodoController; /* ----- todo/index.js ----- */ import angular from "angular"; import TodoComponent from "./todo.component"; const todo = angular .module("todo", []) .component("todo", TodoComponent) .name; export default todo;

這個例子顯示了一個有狀態(tài)的組件,在控制器哪通過服務獲取狀態(tài),然后再將它傳遞給無狀態(tài)的子組件。注意這里并沒有在模版使用指令比如ng-repeat以及其他指令,相反,數(shù)據(jù)和功能委托到 這兩個無狀態(tài)的組件。

無狀態(tài)的組件

什么是無狀態(tài)的組件

使用bindings: {} 定義了輸入和輸出;

數(shù)據(jù)通過屬性綁定進入到組件內

數(shù)據(jù)通過事件離開組件

狀態(tài)變化,會將數(shù)據(jù)進行備份 (比如觸發(fā)點擊和提交事件)

并不需要關心的數(shù)據(jù)來自哪里

可高度重復利用的組件

也被稱作無聲活著表面組件

下面是一個無狀態(tài)組件的例子 (我們使用 作為例子) (僅僅用于演示,省略了部分代碼):

/* ----- todo/todo-form/todo-form.component.js ----- */
import controller from "./todo-form.controller";

const TodoFormComponent = {
  bindings: {
    todo: "<",
    onAddTodo: "&"
  },
  controller,
  template: `
    
` }; export default TodoFormComponent; /* ----- todo/todo-form/todo-form.controller.js ----- */ class TodoFormController { constructor(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({ $event: { todo: this.todo } }); } } TodoFormController.$inject = ["EventEmitter"]; export default TodoFormController; /* ----- todo/todo-form/index.js ----- */ import angular from "angular"; import TodoFormComponent from "./todo-form.component"; const todoForm = angular .module("todo") .component("todo", TodoFormComponent) .value("EventEmitter", payload => ({ $event: payload}); export default todoForm;

請注意組件不獲取狀態(tài),它只是接收,它通過控制器的邏輯去改變一個對象然后通過綁定的屬性將改變后的值傳回給父組件。
在這個例子中,$onChanges周期鉤子 產生一個this.todo的對象克隆并重新分配它,這意味著原數(shù)據(jù)不受影響,直到我們提交表單,沿著單向數(shù)據(jù)流的新的綁定語法"<" 。

路由組件

什么是路由組件

它本質上是個有狀態(tài)的組件,具備路由定義

沒有router.js 文件
*我們使用路由組件去定義它自己的路由邏輯

*數(shù)據(jù)流入到組件是通過路由分解獲得 (當然在控制器中我們通過服務獲得)

在這個例子中,我們將利用現(xiàn)有組件,我們會重構它,使用路由定義和以及組件上的數(shù)據(jù)綁定接收數(shù)據(jù)(在這里我們我們是通過ui-router產生的reslove,這個例子todoData直接映射了數(shù)據(jù)綁定)。我們把它看作一個路由組件,因為它本質上是一個"view":

/* ----- todo/todo.component.js ----- */
import controller from "./todo.controller";

const TodoComponent = {
  bindings: {
    todoData: "<"
  },
  controller,
  template: `
    
` }; export default TodoComponent; /* ----- todo/todo.controller.js ----- */ class TodoController { constructor() {} $onInit() { this.newTodo = { title: "", selected: false }; } $onChanges(changes) { if (changes.todoData) { this.todos = Object.assign({}, this.todoData); } } addTodo({ todo }) { if (!todo) return; this.todos.unshift(todo); this.newTodo = { title: "", selected: false }; } } export default TodoController; /* ----- todo/todo.service.js ----- */ class TodoService { constructor($http) { this.$http = $http; } getTodos() { return this.$http.get("/api/todos").then(response => response.data); } } TodoService.$inject = ["$http"]; export default TodoService; /* ----- todo/index.js ----- */ import angular from "angular"; import TodoComponent from "./todo.component"; import TodoService from "./todo.service"; const todo = angular .module("todo", []) .component("todo", TodoComponent) .service("TodoService", TodoService) .config(($stateProvider, $urlRouterProvider) => { $stateProvider .state("todos", { url: "/todos", component: "todo", resolve: { todoData: TodoService => TodoService.getTodos(); } }); $urlRouterProvider.otherwise("/"); }) .name; export default todo;
指令 基本概念

指令給予了我們的模板,scope ,與控制器綁定,鏈接和許多其他的事情。這些的使用使我們慎重考慮 .component()的存在。指令不應在聲明模板和控制器了,或者通過綁定接收數(shù)據(jù)。指令應該僅僅是為了裝飾DOM使用。這樣,就意味著擴展現(xiàn)有的HTML - 如果用.component()創(chuàng)建。簡而言之,如果你需要自定義DOM事件/ API和邏輯,使用一個指令并將其綁定到一個組件內的模板。如果你需要的足夠的數(shù)量的 DOM變化,postLink生命周期鉤子值得考慮,但是這并不是遷移所有的的DOM操作。你可以給一個無需Angular的地方使用directive

使用指令的小建議:

不要使用模板 ,scope,控制器

一直設置 restrict: "A"

在需要的地方使用 compile and link

記得 $scope.$on("$destroy", fn) 進行銷毀和事件解除;

返回目錄

推薦的屬性

由于指令支持了大多數(shù) .component() 的語法 (模板指令就是最原始的組件), 建議限制指令中的的 Object,以及避免使用錯誤的指令方法。

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) See docs
templateUrl No 使用一個組件
transclude No 使用一個組件
常量 和 類

下面有幾個使用es2015和指令的方法,無論是帶有箭頭函數(shù),更容易的操作,或使用ES2015Class。記住選擇最適合自己或者團隊的方法,并且記住 Angular 2中使用 Class.

下面是一個恒在箭頭函數(shù)的表達式()=>({})使用常量的例子,它返回一個對象面(注意里面與.directive的使用差異()):

/* ----- todo/todo-autofocus.directive.js ----- */
import angular from "angular";

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

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

export default TodoAutoFocus;

/* ----- todo/index.js ----- */
import angular from "angular";
import TodoComponent from "./todo.component";
import TodoAutofocus from "./todo-autofocus.directive";

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

export default todo;

或者用ES2015 Class(注意在注冊指令時手動調用 new TodoAutoFocus)來創(chuàng)建對象:

/* ----- todo/todo-autofocus.directive.js ----- */
import angular from "angular";

class TodoAutoFocus {
  constructor() {
    this.restrict = "A";
  }
  link($scope, $element, $attrs) {
    $scope.$watch($attrs.todoAutofocus, (newValue, oldValue) => {
      if (!newValue) {
        return;
      }
      $timeout(() => $element[0].focus());
    });
  }
}

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

export default TodoAutoFocus;

/* ----- todo/index.js ----- */
import angular from "angular";
import TodoComponent from "./todo.component";
import TodoAutofocus from "./todo-autofocus.directive";

const todo = angular
  .module("todo", [])
  .component("todo", TodoComponent)
  .directive("todoAutofocus", () => new TodoAutoFocus)
  .name;

export default todo;
服務 基本理論

服務本質上是包含業(yè)務邏輯的容器,而我們的組件不應該直接進行請求。服務包含其它內置或外部服務,如$http,我們可以隨時隨地的在應用程序注入到組件控制器。我們在開發(fā)服務有兩種方式,.service() 以及 .factory()。使用ES2015Class,我們應該只使用.service(),通過$inject完成依賴注入。

構建服務Class

下面的 就是使用 ES2015 Class:

/* ----- todo/todo.service.js ----- */
class TodoService {
  constructor($http) {
    this.$http = $http;
  }
  getTodos() {
    return this.$http.get("/api/todos").then(response => response.data);
  }
}

TodoService.$inject = ["$http"];

export default TodoService;

/* ----- todo/index.js ----- */
import angular from "angular";
import TodoComponent from "./todo.component";
import TodoService from "./todo.service";

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

export default todo;

返回目錄

ES2015 以及相關工具
ES2015

使用 Babel 將ES2015進行轉換為當前瀏覽器所支持的代碼

考慮使用 TypeScript 讓你更好的遷移到Angular2

工具

使用 ui-router latest alpha (查看 Readme) 如果你希望支持路由鉆

你可能會在 template: "" 以及 不需要 bindings中遇到一些挫折

考慮使用 Webpack 來編譯es2016的代碼

使用 ngAnnotate 自動完成 $inject 屬性注入

如何使用ngAnnotate with ES6

狀態(tài)管理

考慮使用 Redux 用于 數(shù)據(jù)管理.

Angular Redux

資源

理解 .component() 方法

使用 "require" 與 $onInit

理解生命周期鉤子, $onInit, $onChange, $postLink, $onDestroy

在路由中使用 "resolve"

Redux 以及 Angular 狀態(tài)管理

文檔

關于Angular API Angular documentation.

Github: https://github.com/JackPu/angular-styleguide/blob/master/i18n/zh-cn.md
感謝 @toddmotto 許可

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79732.html

相關文章

  • webpack+es6+angular1.x項目構建

    摘要:技術棧概述大名,顧名思義是在年月正式發(fā)布的一套標準。小名,意為第六次變更。本項目,選擇的是的推薦配置,唯一注意的是全局變量中把的關鍵詞加上。項目結構公共組件目錄,放一些二次封裝的等等片段式的。項目的公用樣式目錄。 技術棧概述 ES2015(ES6) 大名ES2015,顧名思義是 ECMAScript 在2015年6月正式發(fā)布的一套標準。小名ES6,意為ECMAScript第六次變更。(...

    KoreyLee 評論0 收藏0
  • Angular1.x + TypeScript 編碼風格

    摘要:組件還包含數(shù)據(jù)事件的輸入與輸出,生命周期鉤子和使用單向數(shù)據(jù)流以及從父組件上獲取數(shù)據(jù)的事件對象備份。 說明:參照了Angular1.x+es2015的中文翻譯,并將個人覺得不合適、不正確的地方進行了修改,歡迎批評指正。 架構,文件結構,組件,單向數(shù)據(jù)流以及最佳實踐 來自@toddmotto團隊的實用編碼指南 Angular 的編碼風格以及架構已經使用ES2015進行重寫,這些在Angul...

    ytwman 評論0 收藏0
  • webpack 教程資源收集

    學習的過程中收藏了這些優(yōu)秀教程和的項目,希望對你有幫助。 github地址, 有不錯的就更新 官方文檔 中文指南 初級教程 webpack-howto 作者:Pete Hunt Webpack 入門指迷 作者:題葉   webpack-demos 作者:ruanyf 一小時包教會 —— webpack 入門指南 作者:VaJoy Larn   webpack 入門及實踐 作者:...

    Backache 評論0 收藏0
  • angular1.x和angular2+并行,angular1.x 升級 angular2+方案

    摘要:可以在不必打斷其它業(yè)務的前提下,升級應用程序,因為這項工作可以多人協(xié)作完成,在一段時間內逐漸鋪開,下面就方案展開說明主要依賴提供模塊。在混合式應用中,我們同時運行了兩個版本的。這意味著我們至少需要和各提供一個模塊。 angular1.x 升級 angular2+ 方案 我給大家提供的是angular1.x和angular5并行,增量式升級方案,這樣大家可以循序漸進升級自己的應用,不想看...

    Olivia 評論0 收藏0
  • angular,react & vue

    摘要:由進行開發(fā)和維護,代發(fā)布于年月,現(xiàn)在主要是。狀態(tài)是只讀的,只能通過來改變,以避免競爭條件這也有助于調試。文件大小為,而為,為。請記住,性能基準只能作為考慮的附注,而不是作為判斷標準。使用的人員報告說,他們永遠不必閱讀庫的源代碼。 本文當時寫在本地,發(fā)現(xiàn)換電腦很不是方便,在這里記錄下。 angular,react & vue 2018/07/23 2016年,對于JavaScript來說...

    jiekechoo 評論0 收藏0

發(fā)表評論

0條評論

Andrman

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<