成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

AngularJS 風(fēng)格指南 (ES2015)

JaysonWang / 1145人閱讀

摘要:風(fēng)格指南的最佳實踐涵蓋體系結(jié)構(gòu)文件結(jié)構(gòu)組件單向數(shù)據(jù)流和生命周期。模塊概述模塊的設(shè)計直接反應(yīng)了我們的文件結(jié)構(gòu)從而保持了可維護性和可預(yù)測性。指令不應(yīng)再聲明模板和控制器,或者通過綁定接收數(shù)據(jù)。指令應(yīng)該只是用來和互交。

# AngularJS 風(fēng)格指南 (ES2015)

AngularJs1.6.x的最佳實踐.涵蓋體系結(jié)構(gòu),文件結(jié)構(gòu),組件,單向數(shù)據(jù)流和生命周期。 目錄

模塊化體系結(jié)構(gòu)

概述

Root module

Component module

Common module

Low-level modules

文件命名約定

可伸縮文件結(jié)構(gòu)

組件

概述

支持的屬性

控制器

單項數(shù)據(jù)流和事件

有狀態(tài)組件/容器型組件

無狀態(tài)組件/展示型組件

路由組件

指令

概述

推薦的屬性

Constants or Classes

服務(wù)

概述

Classes for Service

樣式

ES2015 and Tooling

狀態(tài)管理

模塊化體系結(jié)構(gòu)

Angular應(yīng)用程序中的每個模塊都應(yīng)該是組件模塊。組件模塊用來封裝邏輯、模板、路由和子組件。

模塊概述

模塊的設(shè)計直接反應(yīng)了我們的文件結(jié)構(gòu), 從而保持了可維護性和可預(yù)測性。我們最好有三個高級模塊: root、component和common。root模塊是用來啟動我們應(yīng)用和相應(yīng)模板的基礎(chǔ)模塊,root模塊中導(dǎo)入component和common模塊作為依賴模塊。component和common模塊則負責(zé)引入Low-level modules,Low-level modules通常包含可重用的組件,控制器,服務(wù),指令,過濾器和測試.

Back to top

Root 模塊

root模塊中定義整個應(yīng)用的根組件,根組件中通常包含路由組件,比如ui-router 中的 ui-view

// app.component.js
export const AppComponent = {
  template: `
    
Hello world
Copyright MyApp 2016.
` };
// app.module.js
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";

export const AppModule = angular
  .module("app", [
    ComponentsModule,
    CommonModule,
    uiRouter
  ])
  .component("app", AppComponent)
  .name;

使用 .component("app", AppComponent) 方法在root模塊中注冊根組件,你可能注意到樣式也被引入到了根組件,我們將在后面的章節(jié)介紹這一點.

Back to top

Components 模塊

所有的可重用組件應(yīng)該注冊在component模塊上。上面例子中展示了我們是如何導(dǎo)入 ComponentsModule 并將它們注冊在root模塊中。這樣做可以輕松的將component模塊移動到任何其他應(yīng)用程序中,因為root模塊與component模塊是分離的。

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;

Back to top

Common module

所有我們不希望用在其他應(yīng)用中的組件應(yīng)該注冊在common模塊上。比如布局、導(dǎo)航和頁腳之類的內(nèi)容。

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;

Back to top

Low-level modules

Low-level module是包含獨立功能的組件模塊,將會被導(dǎo)入到像component module或者是 common module這樣的higher-level module中,下面是一個例子。一定要記住在每個export的模塊最后添加.name。你可能注意到路由定義也在這個模塊中,我們將在本指南后面的章節(jié)中介紹這一點。

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, $urlRouterProvider) => {
    "ngInject";
    $stateProvider
      .state("calendar", {
        url: "/calendar",
        component: "calendar"
      });
    $urlRouterProvider.otherwise("/");
  })
  .name;

Back to top

文件命名約定

保持文件名簡單,并且使用小寫字母,文件名使用 " - "分割,比如 calendar-grid.*.js 。使用 *.component.js 標(biāo)示組件,使用 *.module.js 標(biāo)示模塊

calendar.module.js
calendar.component.js
calendar.service.js
calendar.directive.js
calendar.filter.js
calendar.spec.js
calendar.html
calendar.scss

Back to top

可伸縮文件結(jié)構(gòu)

文件結(jié)構(gòu)是非常重要的,這描述了一個可伸縮和可預(yù)測的結(jié)構(gòu),下面是一個例子。

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

頂級文件夾僅包含index.html and app/,其余的模塊在app/

Back to top

組件 組件概述

組件是帶有控制器的模板,組件可以通過 bindings 定義數(shù)據(jù)或是事件的輸入和輸出,你可以將組件視為完整的代碼段,而不僅僅是 .component() 定義的對象,讓我們探討一些關(guān)于組件的最佳實踐和建議, 然后深入了解如何通過有狀態(tài)的、無狀態(tài)的和路由組件的概念來構(gòu)造它們。

Back to top

支持的屬性

這些是 .component() 支持的屬性

Property Support
bindings Yes, use "@", "<", "&" only
controller Yes
controllerAs Yes, default is $ctrl
require Yes (new Object syntax)
template Yes
templateUrl Yes
transclude Yes

Back to top

控制器

控制器應(yīng)該只和組件一起使用,如果你感覺需要一個控制器,可能你需要的是一個管理這個特定行為的組件。

這是一些使用 Class 定義controllers的建議:

使用 controller: class TodoComponent {...} 這種寫法以應(yīng)對未來向Angular遷移

始終使用 constructor 來進行依賴注入

使用 babel-plugin-angularjs-annotate 的 "ngInject";語法

如果需要訪問詞法作用域,請使用箭頭函數(shù)

除了箭頭函數(shù) let ctrl = this; 也是可以接受的

將所有的公共函數(shù)綁定到 class{}

適當(dāng)?shù)氖褂?$onInit, $onChanges, $postLink and $onDestroy 等生命周期函數(shù)

Note: $onChanges is called before $onInit, see resources section for articles detailing this in more depth

Use require alongside $onInit to reference any inherited logic

Do not override the default $ctrl alias for the controllerAs syntax, therefore do not use controllerAs anywhere

Back to top

單向數(shù)據(jù)流和事件

AngularJS 1.5中引入了單向數(shù)據(jù)流,這重新定義了組件之間的通信.

這里有一些使用單向數(shù)據(jù)流的建議:

在組件中接受數(shù)據(jù)時,總是使用單向數(shù)據(jù)綁定語法 "<"

任何時候都不要在使用雙向綁定語法 "="

使用 bindings 綁定傳入數(shù)據(jù)時,在 $onChanges 生命周期函數(shù)中深復(fù)制傳入的對象以解除父組件的引用

在父組件的方法中使用 $event 作為函數(shù)的參數(shù)(查看下面有狀態(tài)組件的例子$ctrl.addTodo($event))

從無狀態(tài)組件的方法中傳遞回 $event: {} 對象(查看下面的無狀態(tài)組件例子 this.onAddTodo)

Back to top

有狀態(tài)組件

讓我們定義一個有狀態(tài)組件

獲取狀態(tài),實質(zhì)上是通過服務(wù)與后臺API通信

不要直接變化狀態(tài)

一個包括low-level module定義的有狀態(tài)組件的例子(為了簡潔省略了一些代碼)

/* ----- todo/todo.component.js ----- */
import templateUrl from "./todo.html";

export const TodoComponent = {
  templateUrl,
  controller: class TodoComponent {
    constructor(TodoService) {
      "ngInject";
      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
      };
    }
  }
};

/* ----- todo/todo.html ----- */
/* ----- todo/todo.module.js ----- */ import angular from "angular"; import { TodoComponent } from "./todo.component"; import "./todo.scss"; export const TodoModule = angular .module("todo", []) .component("todo", TodoComponent) .name;

這個例子展示了一個有狀態(tài)組件,在控制器中通過服務(wù)獲取數(shù)據(jù),然后傳遞給無狀態(tài)子組件。注意我們在模板中并沒有使用ng-repeat 之類的指令,而是委托給 組件

Back to top

無狀態(tài)組件

讓我們第一我們所謂的無狀態(tài)組件:

使用 bindings: {} 明確的定義輸入和輸出

通過屬性綁定傳遞數(shù)據(jù)

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

不要關(guān)心數(shù)據(jù)來自哪里 - 它是無狀態(tài)的

是高度可重用的組件

也被稱為展示型組件

一個無狀態(tài)組件的例子( 為了簡潔省略了一些代碼)

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

export const TodoFormComponent = {
  bindings: {
    todo: "<",
    onAddTodo: "&"
  },
  templateUrl,
  controller: class TodoFormComponent {
    constructor(EventEmitter) {
        "ngInject";
        this.EventEmitter = EventEmitter;
    }
    $onChanges(changes) {
      if (changes.todo) {
        this.todo = Object.assign({}, this.todo);
      }
    }
    onSubmit() {
      if (!this.todo.title) return;
      // with EventEmitter wrapper
      this.onAddTodo(
        this.EventEmitter({
          todo: this.todo
        })
      );
      // without EventEmitter wrapper
      this.onAddTodo({
        $event: {
          todo: this.todo
        }
      });
    }
  }
};

/* ----- todo/todo-form/todo-form.html ----- */
/* ----- todo/todo-form/todo-form.module.js ----- */ import angular from "angular"; import { TodoFormComponent } from "./todo-form.component"; import "./todo-form.scss"; export const TodoFormModule = angular .module("todo.form", []) .component("todoForm", TodoFormComponent) .value("EventEmitter", payload => ({ $event: payload })) .name;

注意, 組件沒有狀態(tài),僅僅是接收數(shù)據(jù),通過屬性綁定的事件傳遞數(shù)據(jù)回到父組件。上例中,在 $onChanges 函數(shù)內(nèi)深復(fù)制了 this.todo ,這意味著在提交回父組件前,父組件的數(shù)據(jù)是不受影響的,

Back to top

路由組件

讓我們定義一個路由組件。

一個帶有路由定義的有狀態(tài)組件

沒有 router.js 文件

使用路由組件來定義他們自己的路由邏輯

組件數(shù)據(jù)的輸入是通過路由的 resolve

在這個例子中,我們將使用路由定義和 bindings重構(gòu) 組件.我們將其視為路由組件,因為它本質(zhì)上是一個"視圖"

/* ----- todo/todo.component.js ----- */
import templateUrl from "./todo.html";

export const TodoComponent = {
  bindings: {
    todoData: "<"
  },
  templateUrl,
  controller: class TodoComponent {
    constructor() {
      "ngInject"; // Not actually needed but best practice to keep here incase dependencies needed in the future
    }
    $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
      };
    }
  }
};

/* ----- todo/todo.html ----- */
/* ----- todo/todo.service.js ----- */ export class TodoService { constructor($http) { "ngInject"; this.$http = $http; } getTodos() { return this.$http.get("/api/todos").then(response => response.data); } } /* ----- todo/todo.module.js ----- */ import angular from "angular"; import uiRouter from "angular-ui-router"; import { TodoComponent } from "./todo.component"; import { TodoService } from "./todo.service"; import "./todo.scss"; export const TodoModule = angular .module("todo", [ uiRouter ]) .component("todo", TodoComponent) .service("TodoService", TodoService) .config(($stateProvider, $urlRouterProvider) => { "ngInject"; $stateProvider .state("todos", { url: "/todos", component: "todo", resolve: { todoData: TodoService => TodoService.getTodos() } }); $urlRouterProvider.otherwise("/"); }) .name;

Back to top

指令 指令概述

指令有 template, scope 綁定, bindToController, link 和很多其他特性。在基于組件的應(yīng)用中應(yīng)該注意他們的使用。指令不應(yīng)再聲明模板和控制器,或者通過綁定接收數(shù)據(jù)。指令應(yīng)該只是用來和DOM互交。簡單來說,如果你需要操作DOM,那就寫一個指令,然后在組件的模板中使用它。如果您需要大量的DOM操作,還可以考慮$ postLink生命周期鉤子,但是,這不是讓你將所有DOM操作遷移到這個函數(shù)中。

這有一些使用指令的建議:

不要在使用 templates, scope, bindToController or controllers

指令總是使用 restrict: "A"

必要時使用編譯和鏈接函數(shù)

記住在 $scope.$on("$destroy", fn); 中銷毀和解除綁定事件處理程序

Back to top

推薦的屬性

由于指令支持.component()所做的大多數(shù)事情(指令是原始組件),我建議將指令對象定義限制為僅限于這些屬性,以避免錯誤地使用指令:

Property Use it? Why
bindToController No Use bindings in components
compile Yes For pre-compile DOM manipulation/events
controller No Use a component
controllerAs No Use a component
link functions Yes For pre/post DOM manipulation/events
multiElement Yes See docs
priority Yes See docs
require No Use a component
restrict Yes Defines directive usage, always use "A"
scope No Use a component
template No Use a component
templateNamespace Yes (if you must) See docs
templateUrl No Use a component
transclude No Use a component

Back to top

Constants or Classes

在ES2015中有幾種方式使用指令,要么通過箭頭函數(shù),要么使用 Class,選擇你認為合適的。

下面是一個使用箭頭函數(shù)的例子:

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

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

/* ----- todo/todo.module.js ----- */
import angular from "angular";
import { TodoComponent } from "./todo.component";
import { TodoAutofocus } from "./todo-autofocus.directive";
import "./todo.scss";

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

或者使用 ES2015 Class 創(chuàng)建一個對象(注意在注冊指令時手動調(diào)用 "new TodoAutoFocus")

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

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

/* ----- todo/todo.module.js ----- */
import angular from "angular";
import { TodoComponent } from "./todo.component";
import { TodoAutofocus } from "./todo-autofocus.directive";
import "./todo.scss";

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

Back to top

服務(wù) 服務(wù)概述

服務(wù)本質(zhì)上是業(yè)務(wù)邏輯的容器。服務(wù)包含其他內(nèi)置或外部服務(wù)例如$http,我們可以在應(yīng)用的其他位置注入到控制器中。我們有兩種使用服務(wù)的方式,.service().factory()。如果要使用ES2015的 Class,我們應(yīng)該使用.service(),并且使用$inject自動完成依賴注入。

Back to top

Classes for Service

這是一個使用 ES2015 Class的例子:

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

/* ----- todo/todo.module.js ----- */
import angular from "angular";
import { TodoComponent } from "./todo.component";
import { TodoService } from "./todo.service";
import "./todo.scss";

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

Back to top

樣式

使用 Webpack 我們可以在*.module.js 中用 import 導(dǎo)入我們的 .scss 文件,這樣做可以讓我們的組件在功能和樣式上都是隔離的。

如果你有一些變量或全局使用的樣式,比如表單輸入元素,那么這些文件仍然應(yīng)該放在根目錄scss文件夾中。 例如 SCSS / _forms.scss。這些全局樣式可以像通常那樣被 @importe.

Back to top

ES2015 and Tooling
ES2015

使用Babel編譯你寫的ES2015+代碼

考慮使用TypeScript

Tooling

如果想支持組件路由,那么使用 ui-router latest alpha

使用 Webpack 編譯你的ES2015+代碼和樣式

使用webpack的ngtemplate-loader

使用babel的babel-plugin-angularjs-annotate

Back to top

狀態(tài)管理

考慮使用redux管理你應(yīng)用的狀態(tài).

Angular Redux

Back to top

資源

Stateful and stateless components, the missing manual

Understanding the .component() method

Using "require" with $onInit

Understanding all the lifecycle hooks, $onInit, $onChanges, $postLink, $onDestroy

Using "resolve" in routes

Redux and Angular state management

Sample Application from Community

Back to top

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/93368.html

相關(guān)文章

  • Angular1.x + TypeScript 編碼風(fēng)格

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

    ytwman 評論0 收藏0
  • 前端練級攻略(第二部分)

    摘要:是文檔的一種表示結(jié)構(gòu)。這些任務(wù)大部分都是基于它。這個實踐的重點是把你在前端練級攻略第部分中學(xué)到的一些東西和結(jié)合起來。一旦你進入框架部分,你將更好地理解并使用它們。到目前為止,你一直在使用進行操作。它是在前端系統(tǒng)像今天這樣復(fù)雜之前編寫的。 本文是 前端練級攻略 第二部分,第一部分請看下面: 前端練級攻略(第一部分) 在第二部分,我們將重點學(xué)習(xí) JavaScript 作為一種獨立的語言,如...

    BWrong 評論0 收藏0
  • 【譯】前端練級攻略

    摘要:由于系統(tǒng)變得越來越復(fù)雜,人們提出了稱為預(yù)處理器和后處理器的工具來管理復(fù)雜性。后處理器在由預(yù)處理器手寫或編譯后對應(yīng)用更改。我之前建議的文章,,也涵蓋了預(yù)處理器相關(guān)的知識。 譯者:前端小智 原文:medium.freecodecamp.org/from-zero-t… medium.freecodecamp.org/from-zero-t… 我記得我剛開始學(xué)習(xí)前端開發(fā)的時候。我看到了很多文章及...

    wuyumin 評論0 收藏0
  • 前端文檔收集

    摘要:系列種優(yōu)化頁面加載速度的方法隨筆分類中個最重要的技術(shù)點常用整理網(wǎng)頁性能管理詳解離線緩存簡介系列編寫高性能有趣的原生數(shù)組函數(shù)數(shù)據(jù)訪問性能優(yōu)化方案實現(xiàn)的大排序算法一怪對象常用方法函數(shù)收集數(shù)組的操作面向?qū)ο蠛驮屠^承中關(guān)鍵詞的優(yōu)雅解釋淺談系列 H5系列 10種優(yōu)化頁面加載速度的方法 隨筆分類 - HTML5 HTML5中40個最重要的技術(shù)點 常用meta整理 網(wǎng)頁性能管理詳解 HTML5 ...

    jsbintask 評論0 收藏0

發(fā)表評論

0條評論

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