Skip to content

Latest commit

 

History

History
849 lines (686 loc) · 47.7 KB

README-ro-ro.md

File metadata and controls

849 lines (686 loc) · 47.7 KB

Join the chat at https://gitter.im/mgechev/angularjs-style-guide

Introducere

Scopul acestui ghid de stil este de a prezenta un set dintre cele mai bune practici și linii de ghidaj de stil pentru o aplicația AngularJS.

Acest cele mai bune practici sunt colecționate din:

  1. Codul sursă AngularJS
  2. Codul sursă al articolelor pe care le-am citit
  3. Propria mea experiență

Note 1: acest text este încă o schiță a ghidului de stil, scopul său principal este de a fi condus de către comunitate, astfel încât umplerea golurilor să fie apreciată de întreaga comunitate.

Note 2: înainte de a urma orice linie de ghidaj de stil din traducerile documentului din engleză, asigură-te că este adus la zi. Ultima versione a ghidului de stil pentru AngularJS este documentul în engleză.

În acest ghid de stil nu voi urma linii de ghidaj de stil comune pentru dezvoltarea în JavaScript. Acestea pot fi găsite în:

  1. Ghidul de stil pentru JavaScript folosit de Google
  2. Ghidul de stil pentru JavaScript folosit de Mozilla
  3. Ghidul de stil pentru JavaScript folosit de Douglas Crockford
  4. Ghidul de stil pentru JavaScript folosit de Airbnb
  5. Ghidul de stil pentru JavaScript folosit de Idiomatic

Pentru dezvoltare în AngularJS este recomandat Ghidul de stil pentru JavaScript folosit de Google.

În wiki-ul AngularJS de pe Github există o secțiune similară făcută de ProLoser, o poți verifica aici.

Traduceri

Conținut

General

Structura directorului

Deoarece o aplicație AngularJS are multe componente este cel mai bine să o structurezi într-o ierarhie de directoare. Există două metode principale:

  • Crearea de diviziuni de nivel înalt bazate pe tipuri de componente și divizuni de nivel jos bazate pe funcționalitate.

În acest fel, structura directorului va arăta astfel:

.
├── app
│   ├── app.js
│   ├── controllers
│   │   ├── home
│   │   │   ├── FirstCtrl.js
│   │   │   └── FirstCtrl.spec.js
│   │   │   └── SecondCtrl.js
│   │   │   └── SecondCtrl.spec.js
│   │   └── about
│   │       └── ThirdCtrl.js
│   │       └── ThirdCtrl.spec.js
│   ├── directives
│   │   ├── home
│   │   │   └── directive1.js
│   │   │   └── directive1.spec.js
│   │   └── about
│   │       ├── directive2.js
│   │       ├── directive2.spec.js
│   │       └── directive3.js
│   │       └── directive3.spec.js
│   ├── filters
│   │   ├── home
│   │   └── about
│   └── services
│       ├── CommonService.js
│       ├── CommonService.spec.js
│       ├── cache
│       │   ├── Cache1.js
│       │   ├── Cache1.spec.js
│       │   └── Cache2.js
│       │   └── Cache2.spec.js
│       └── models
│           ├── Model1.spec.js
│           ├── Model1.js
│           └── Model2.spec.js
│           └── Model2.js
├── partials
├── lib
└── e2e-tests
  • Crearea de diviziuni de nivel înalt bazate pe funcționalitate și divizuni de nivel jos bazate pe tipuri de componente.

Aceasta este organizarea:

.
├── app
│   ├── app.js
│   ├── common
│   │   ├── controllers
│   │   ├── directives
│   │   ├── filters
│   │   └── services
│   ├── home
│   │   ├── controllers
│   │   │   ├── FirstCtrl.js
│   │   │   ├── FirstCtrl.spec.js
│   │   │   └── SecondCtrl.js
│   │   │   └── SecondCtrl.spec.js
│   │   ├── directives
│   │   │   └── directive1.js
│   │   │   └── directive1.spec.js
│   │   ├── filters
│   │   │   ├── filter1.js
│   │   │   ├── filter1.spec.js
│   │   │   └── filter2.js
│   │   │   └── filter2.spec.js
│   │   └── services
│   │       ├── service1.js
│   │       ├── service1.spec.js
│   │       └── service2.js
│   │       └── service2.spec.js
│   └── about
│       ├── controllers
│       │   └── ThirdCtrl.js
│       │   └── ThirdCtrl.spec.js
│       ├── directives
│       │   ├── directive2.js
│       │   ├── directive2.spec.js
│       │   └── directive3.js
│       │   └── directive3.spec.js
│       ├── filters
│       │   └── filter3.js
│       │   └── filter3.spec.js
│       └── services
│           └── service3.js
│           └── service3.spec.js
├── partials
├── lib
└── e2e-tests
  • În cazul în care un nume de director conține mai multe cuvinte, folosește sintaxa-tip-lisp:
app
 ├── app.js
 └── my-complex-module
     ├── controllers
     ├── directives
     ├── filters
     └── services
  • Pune toate fișierele asociate cu o directivă (i.e. șabloane, fișiere CSS/SASS, JavaScript) într-un singur director. Dacă alegi să folosești acest stil, fii consistent și folosește-l peste tot în proiectul tău.
app
└── directives
    ├── directive1
    │   ├── directive1.html
    │   ├── directive1.js
    │   ├── directive1.spec.js
    │   └── directive1.sass
    └── directive2
        ├── directive2.html
        ├── directive2.js
        ├── directive2.spec.js
        └── directive2.sass

Această metodă poate fi combinată cu ambele structuri de directoare de mai sus.

  • Testele de unitate pentru un anumit component (*.spec.js) ar trebui să fie localizate în directorul în care se află componentul. În acest fel poți face schimbări la un anumit component deoarece testarea este ușoară. Testele funcționează de asemenea ca documentare și studii de caz.
services
├── cache
│   ├── cache1.js
│   └── cache1.spec.js
└── models
    ├── model1.js
    └── model1.spec.js
  • Fișierul app.js ar trebui să conțină definiții de rute, configurație și/sau autoinițializare manuală (dacă este necesar).
  • Fiecare fișier de JavaScript ar trebui să conțină un singur component. Fișierul ar trebui să fie numit cu numele componentului.
  • Folosește șablonul structurii de proiect precum Yeoman, ng-boilerplate.

Convenții despre numirea componentelor pot fi găsite în secțiunea fiecărui component.

Marcaj

PL;NC Pune script-urile la final.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>MyApp</title>
</head>
<body>
  <div ng-app="myApp">
    <div ng-view></div>
  </div>
  <script src="angular.js"></script>
  <script src="app.js"></script>
</body>
</html>

Păstrează lucrurile simplu și pune directive specifice AngularJS după atributele standard. Aceasta va face parcurgerea codului mai ușoară și va fi mai ușor de menținut deoarece atributele sunt grupate și poziționate consistent.

<form class="frm" ng-submit="login.authenticate()">
  <div>
    <input class="ipt" type="text" placeholder="name" require ng-model="user.name">
  </div>
</form>

Alte atribute HTML ar trebui să urmeze recomandarea Code Guide

Convenții de numire

Următorul tabel arată convențiile de numere pentru fiecare element:

Element Stil de numire Exemplu Folosire
Module scrieCamilăMic angularApp
Controlere Funcționalitate + 'Ctrl' AdminCtrl
Directive scrieCamilăMic userInfo
Filtre scrieCamilăMic userFilter
Servicii scrieCamilăMare User constructor
Fabrici scrieCamilăMic dataFactory others

Altele

  • Folosește:
    • $timeout în loc de setTimeout
    • $interval în loc de setInterval
    • $window în loc de window
    • $document în loc de document
    • $http în loc de $.ajax
    • $location în loc de window.location sau $window.location
    • $cookies în loc de document.cookie

Asta îți va face testarea mai ușoară iar în unele cazuri va preveni comportamentul neașteptat (de exemplu, dacă ai uitat $scope.$apply în setTimeout).

  • Automează-ți fluxul de lucru folosind unelte ca:

  • Folosește promisiuni ($q) în loc de reveniri. Îți va face codul să arate mai elegant și mai curat, și te va scăpa de iadul revenirilor.

  • Folosește $resource în loc de $http atunci când este posibil. Nivelul mai înalt de abstracție te va scăpa de redundanță.

  • Folosește un pre-minificator AngularJS (ng-annotate) pentru a preveni problemele de după minificare.

  • Nu folosi globale. Rezolvă toate dependențele folosind Injectarea Dependențelor, aceasta va preveni bug-urile și cârpirea codului la testare.

  • Evită globalele folosind Grunt/Gulp pentru a înveli codul în Expresii Funcții Invocate Imediat (EFII/IIFE). Poți folosi plugin-uri ca grunt-wrap sau gulp-wrap pentru acest scop. Exemplu (folosind Gulp)

    gulp.src("./src/*.js")
    .pipe(wrap('(function(){\n"use strict";\n<%= contents %>\n})();'))
    .pipe(gulp.dest("./dist"));
  • Nu-ți polua $scope-ul. Adaugă doar funcții și variable care sunt folosite în șabloane.

  • Preferă folosirea controlerelor în loc de ngInit. Există doar câteva folosiri adecvate pentru ngInit, de exemplu pentru redenumirea proprietăților speciale în ngRepeat, și pentru injectarea de data prin scriptare din partea server-ului. Pe lângă aceste câteva cazuri, ar trebui să folosești controlere mai degrabă decât ngInit pentru a inițializa valori într-un scop. Expresia predată luingInit ar trebui să treacă prin lexicalizare, parsare și evaluare de către interpretatorul Angular implementat în serviciul $parse. Aceasta conduce la:

    • Impact asupra performanței, deoarece interpretatorul este implementat în JavaScript;
    • Arhivarea expresiilor parsate în interiorul serviciului $parse nu are mult sens în cele mai multe cazuri, deoarece expresiile ngInit sunt evaluate doar o dată;
    • Este dispus erorii, deoarece scrii șiruri de caractere în interiorul șabloanelor nu există evidențierea sintaxei și suport adițional din partea editorului.
    • Nu sunt aruncate erori la rulare
  • Nu folosi $ ca prefix pentru numele variabilelor, proprietăților, sau metodelor. Acest prefix este rezervat pentru folosirea de către AngularJS.

  • Nu folosi JQUERY în interiorul aplicației. Dacă trebuie, folosește în loc JQLite cu angular.element.

  • Atunci când rezolvi dependențe prin mecanismul de Injectarea Dependențelor al AngularJS sortează dependențele prin tipul lor - dependențele contruite-în AngularJS ar trebui să fie primele, urmate de cele ale tale:

module.factory('Service', function ($rootScope, $timeout, MyCustomDependency1, MyCustomDependency2) {
  return {
    //Something
  };
});

Module

  • Modulele ar trebui să fie numite cu scriereCămilăMic. Pentru a indica că modulul b este un submodul al modulului a le poți încorpora folosind înspațierea în nume ca: a.b.

    Există două feluri comune de a structura modulele:

    1. Prin funcționalitate
    2. Prin tipul componentului

    Momentan, nu este o diferență majoră, dar primul mod arată mai curat. De asemenea, dacă încărcarea-leneșă a modulelor este implementată (momentan nu este în harta de dezvoltare a AngularJS), va crește performanța aplicației.

Controlere

  • Nu manipula DOM-ul în controlere, aceasta va face controlerele mai greu de testat și va viola Principiul de Separare a Grijilor. Folosește directive în schimb.

  • Numirea controlerului este făcută folosind funcționalitatea controlerului (de exemplu coș de cumpărături, pagină principală, panou admin) și subșirul Ctrl la final.

  • Controlere sunt constructori în JavaScript simplu, astfel că vor fi numite folosind ScriereaCămilăMare (HomePageCtrl, ShoppingCartCtrl, AdminPanelCtrl, etc.).

  • Controlerele nu ar trebui să fie definite ca globale (chiar dacă AngularJS permite asta, este o practică proastă să poluezi înspațierea de nume global).

  • Folosește următoarea sintaxă pentru definirea controlerelor:

    function MyCtrl(dependency1, dependency2, ..., dependencyN) {
      // ...
    }
    module.controller('MyCtrl', MyCtrl);

    Pentru a preveni problemele cu minificarea poți genera automat sintaxa de definire a matricii din cea standard foloding unelte ca ng-annotate (și grunt grunt-ng-annotate).

    O altă alternativă va fi de a folosi $inject ca:

    angular
      .module('app')
      .controller('HomepageCtrl', HomepageCtrl);
    
    HomepageCtrl.$inject = ['$log', '$http', 'ngRoute'];
    
    function HomepageCtrl($log, $http, ngRoute) {
      // ...
    }
  • Evită de a folosi serviciul $scope pentru a defini funcții și proprietăți ca părți ale controlerelor. Folosește $scope doar dacă este necesar: 0. Pentru publicarea și subscrierea la evenimente: $scope.$emit, $scope.$broadcast, și $scope.$on. 0. Pentru valori și colecții watch: $scope.$watch, $scope.$watchCollection

  • Preferă folosirea sintaxei controller as și capturează this folosind o variabilă:

    <div ng-controller="MainCtrl as main">
       {{ main.things }}
    </div>
    app.controller('MainCtrl', MainCtrl);
    MainCtrl.$inject = ['$http'];
    
    function MainCtrl ($http) {
      var vm = this;
      // o conexiune vizuală mai clară despre cum este definită în vedere
      vm.title = 'Some title';
      vm.description = 'Some description';
    
      $http.get('/api/main/things').then(function (response) {
          vm.things = response.data.things; // Adăugarea 'things' ca proprietate a controlerului
      });
    }

    Evită folosirea cuvântului this în mod repetat într-un controler:

      app.controller('MainCtrl', MainCtrl);
      MainCtrl.$inject = ['$http'];
    
      // evită
      function MainCtrl ($http) {
        this.title = 'Some title';
        this.description = 'Some description';
    
        $http.get('/api/main/things').then(function (response) {
            // Atenție! 'this' este în alt context aici
            // Proprietatea nu va fi adăugată ca parte a contextului controlerului
            this.things = response.data.things;
        });
      }

    Folosirea unui nume consistent și scurt este preferat, de exemplu vm.

    Beneficiile principale de a folosi această sintaxă:

    • Creează un component 'izolat' - proprietățile legate nu sunt parte a lanțului prototipal $scope. Aceasta este o practică deoarece ereditatea prototipală a $scope are câteva dezavantaje majore (acesta este probabil motivul pentru a care a fost scos din Angular 2):
      • Este greu de ținut cont de unde vine data.
      • Schimbările valorile scopului pot afecta locuri pe caren nu ai intenționat să le afectezi.
      • Mai greu de refactorizat.
      • 'regula punct'.
    • Renunță la folosirea $scope acolo unde nu este nevoie de operații speciale (așa cum este menționat mai sus). Aceasta este o bună pregătire pentru AngularJS V2.
    • Sintaxa este mai apropiată de constructorul JavaScript 'vanilie'.

    Săpând mai adânc în controller as: săpând-în-controlerele-angular-ca-sintaxă

  • În folosirea sintaxei de definirea matricei, folosește numele originale ale dependenței controlerelor. Aceasta te va ajuta să produci un cod mai citibil:

    function MyCtrl(l, h) {
      // ...
    }
    
    module.controller('MyCtrl', ['$log', '$http', MyCtrl]);

    care este mai puțin citibil decât:

    function MyCtrl($log, $http) {
      // ...
    }
    
    module.controller('MyCtrl', ['$log', '$http', MyCtrl]);

    Aceasta se aplică în mod special la un fișier care are atât de mult cod încât trebuie să faci scroll prin el. Aceasta te va face poate să uiți ce variabilă este legată de care dependență.

  • Fă controlerele cât mai subțiri. Abstractiează funcțiile folosite în mod comun într-un serviciu.

  • Evită scrierea logicii de afacere în interiroul controlerelor. Delegă logica de afacere într-un model, folosind un serviciu. De exemplu:

    // Acesta este un comportament comun (exemplu negativ) de a folosi logica de afacere în interiorul unui controler.
    angular.module('Store', [])
    .controller('OrderCtrl', function () {
      var vm = this;
    
      vm.items = [];
    
      vm.addToOrder = function (item) {
        vm.items.push(item);//--> Logică de afacere în interiorul controlerului
      };
    
      vm.removeFromOrder = function (item) {
        vm.items.splice(vm.items.indexOf(item), 1);//--> Logică de afacere în interiorul controlerului
      };
    
      vm.totalPrice = function () {
        return vm.items.reduce(function (memo, item) {
          return memo + (item.qty * item.price);//--> Logică de afacere în interiorul controlerului
        }, 0);
      };
    });

    Atunci când delegi logica de afacere într-un serviciu de model, controlerul va arăta atfel (vezi 'folosește servicii ca Model' pentru implementarea serviciului-model):

    // order este folosit ca 'model'
    angular.module('Store', [])
    .controller('OrderCtrl', function (order) {
      var vm = this;
    
      vm.items = order.items;
    
      vm.addToOrder = function (item) {
        order.addToOrder(item);
      };
    
      vm.removeFromOrder = function (item) {
        order.removeFromOrder(item);
      };
    
      vm.totalPrice = function () {
        return order.total();
      };
    });

    De ce logica de afacere / starea aplicației din interiorul controlerului este rea?

    • Controlerele sunt instanțiate pentru fiecare vedere și moare atunci când vederea este descărcată.
    • Controlerele nu sunt refolosibile - ele sunt cuplat cu vederea.
    • Controlerele nu sunt menite să fie injectate.
  • Comunică în cadrul diferitelor controlere folosind invocarea metodei (posibilă atunci când un copil vrea să comunice cu părintele său) sau metodele $emit, $broadcast, și $on. Mesajele emise sau comunicate ar trebui să fie păstrate la un minim.

  • Fă o listă a tuturor mesajelor care sunt predate prin $emit, $broadcast și administreaz-o cu atenție datorită coliziunilor de nume și a posibilelor bug-uri.

    Exemple:

    // app.js
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    Evenimente specifice:
      - 'authorization-message' - descrierea mesajului
        - { user, role, action } - formatul data
          - user - un șir de caractere, care conține numele de utilizator
          - role - un ID al unui rol avut de utilizator
          - action - acțiunea specifică pe care încearcă să o facă utilizatorul
    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  • Atunci când trebuie să formatezi data, encapsulează logica de formatare într-un filtru și declar-o ca o dependență:

    function myFormat() {
      return function () {
        // ...
      };
    }
    module.filter('myFormat', myFormat);
    
    function MyCtrl($scope, myFormatFilter) {
      // ...
    }
    
    module.controller('MyCtrl', MyCtrl);
  • În cazul controlerelor grupate folosește „scope grupat” (sintaxa controllerAs):

    app.js

    module.config(function ($routeProvider) {
      $routeProvider
        .when('/route', {
          templateUrl: 'partials/template.html',
          controller: 'HomeCtrl',
          controllerAs: 'home'
        });
    });

    HomeCtrl

    function HomeCtrl() {
      var vm = this;
    
      vm.bindingValue = 42;
    }

    template.html

    <div ng-bind="home.bindingValue"></div>

Directive

  • Numește-ți directive cu scriereCămilăMică.
  • Folosește scope în locul $scope în funcția de legare. În funcțiile de compilare, pre/post legare ai definit deja argumente care vor fi predate atunci când funcția este invocată, nu vei fi capabil să le schimbi atunci când folosești Injectarea Dependenței. Acest stil este de asemenea folosit în codul sursă AngularJS.
  • Folosește prefixe specifice pentru directive pentru a preveni coliziunile cu biblioteci ale unor părți terțiare.
  • Nu folosi prefixe ng sau ui deoarece sunt rezervate pentru folosirea AngularJS sau AngularJS UI.
  • Manipularea DOM trebuie făcută doar prin directive.
  • Creează un scop izolat atunci când dezvolți componente reutilizabile.
  • Folosește directive ca atribute sau elemente în loc de comentarii sau clase, îți vor face codul mai citibil.
  • Folosește scope.$on('$destroy', fn) pentru curățire. Aceasta este în special folosibil atunci când învelești directive sau plugin-uri din părți terțe.
  • Nu uita să folosești $sce atunci când ar trebui să lucrezi cu conținut ce nu poate fi crezut.

Filtre

  • Numește-ți filtrele folosind scriereCămilăMic.
  • Fă-ți filtrele cât mai ușoare posibil. Ele sunt chemate des în timpul ciclului $digest astfel încât crearea unui filtru încet îți va încetini aplicația.
  • Fă un singur lucru în filtre, păstrează-le coerente. Manipulări mai complexe pot fi obținute prin înțevuirea filtrele existente.

Servicii

Această secțiune include informație despre serviciul component în AngularJS. Nu este dependent de felul definiției (i.e. ca furnizor, .factory, .service), cu excepția dacă este menționată explicit.

  • Folosirea scriereCămilăMic pentru a-ți numi serviciile.

  • ScriereaCămilăMare (ScriereaPascal) pentru numirea serviciilor, folosite ca funcții constructor, i.e.:

    function MainCtrl(User) {
        var vm = this;
        vm.user = new User('foo', 42);
    }
    
    module.controller('MainCtrl', MainCtrl);
    
    function User(name, age) {
      this.name = name;
      this.age = age;
    }
    
    module.factory('User', function () {
      return User;
    });
  • scriereCămilăMic pentru toate celelalte servicii.

  • Encapsulează-ți toată logica de afaceri în servicii. Preferă să o folosești ca model. De exemplu:

    // order este 'model'-ul
    angular.module('Store')
    .factory('order', function () {
        var add = function (item) {
          this.items.push (item);
        };
    
        var remove = function (item) {
          if (this.items.indexOf(item) > -1) {
            this.items.splice(this.items.indexOf(item), 1);
          }
        };
    
        var total = function () {
          return this.items.reduce(function (memo, item) {
            return memo + (item.qty * item.price);
          }, 0);
        };
    
        return {
          items: [],
          addToOrder: add,
          removeFromOrder: remove,
          totalPrice: total
        };
    });
  • Vezi 'Evitarea scrierii logicii de afaceri în controlere' pentru un exemplu a unui controler care consumă acest serviciu.

  • Serviciile reprezentând domeniul preferă un service în loc de un factory. În acest fel putem valorifica de ereditarea "klassical"ă mai ușor:

    function Human() {
      //body
    }
    Human.prototype.talk = function () {
      return "I'm talking";
    };
    
    function Developer() {
      //body
    }
    Developer.prototype = Object.create(Human.prototype);
    Developer.prototype.code = function () {
      return "I'm coding";
    };
    
    myModule.service('human', Human);
    myModule.service('developer', Developer);
  • Pentru arhivarea la nivel de sesiune poți folosi $cacheFactory. Aceasta ar trebui să fie folosită pentru a arhiva rezultate din cereri și computații grele.

  • Dacă un anumit serviciu necesită configurare, definește serviciul ca furnizor și configurează-l în revenirea config ca:

    angular.module('demo', [])
    .config(function ($provide) {
      $provide.provider('sample', function () {
        var foo = 42;
        return {
          setFoo: function (f) {
            foo = f;
          },
          $get: function () {
            return {
              foo: foo
            };
          }
        };
      });
    });
    
    var demo = angular.module('demo');
    
    demo.config(function (sampleProvider) {
      sampleProvider.setFoo(41);
    });

Șabloane

  • Folosește ng-bind sau ng-cloak în loc de simple {{ }} pentru a preveni fulgerarea conținutului.
  • Evită scrierea de expresii complexe în șabloane.
  • Atunci când trebuie să setezi src-ul unei imagini dinamic folosește ng-src în loc de src cu șablon {{ }}.
  • Atunci când trebuie să setezi href-ul unei etichete ancoră dinamic folosește ng-href în loc de href cu șablon {{ }}.
  • În loc de a folosi variabile de scop ca șir de caractere și a folosi atributul style cu {{ }}, folosește directiva ng-style cu parametri ca-obiecte și variabile de scop ca valori:
    <div ng-controller="MainCtrl as main">
        <div ng-style="main.divStyle">my beautifully styled div which will work in IE</div>;
    </div>
  angular
    .module('app')
    .controller('MainCtrl', MainCtrl);

  MainCtrl.$inject = [];

  function MainCtrl() {
    var vm = this;
    vm.divStyle = {
        width: 200,
        position: 'relative'
    };
  }

Rute

  • Folosește resolve pentru a rezolva dependențele înainte ca vederea să fie aratată.
  • Nu plasa chemări explicite REST înăutru revenirii resolve. Izolează toate cererile înăutru serviciilor adecvate. În acest fel poți activa arhivarea și urmări principiul separării grijei.

Testare CLC

Testarea Capăt-La-Capăt sunt pasul următor după testele de unitate care-ți vor permite să urmărești bug-urile și erorile din sistem. Sunt foarte utile în a asigura o verificare de sanitate în cele mai comune scenarii din folosirea aplicației tale. În acest fel poți automatiza procesul și rula înainte de fiecare dată de ați instala aplicația.

Ideal, teste Capăt-La-Capăt Angular sunt scrise în Jasmine. Aceste teste sunt rulate folosind Protractor E2E care folosește evenimente native și are funcții speciale pentru aplicații Angular.

Structura fișierelor:

.
├── app
│   ├── app.js
│   ├── home
│   │   ├── home.html
│   │   ├── controllers
│   │   │   ├── FirstCtrl.js
│   │   │   ├── FirstCtrl.spec.js
│   │   ├── directives
│   │   │   └── directive1.js
│   │   │   └── directive1.spec.js
│   │   ├── filters
│   │   │   ├── filter1.js
│   │   │   └── filter1.spec.js
│   │   └── services
│   │       ├── service1.js
│   │       └── service1.spec.js
│   └── about
│       ├── about.html
│       ├── controllers
│       │   └── ThirdCtrl.js
│       │   └── ThirdCtrl.spec.js
│       └── directives
│           ├── directive2.js
│           └── directive2.spec.js
├── partials
├── lib
└── e2e-tests
    ├── protractor.conf.js
    └── specs
        ├── home.js
        └── about.js

i18n

  • Pentru versiuni mai noi ale framework-ului (>=1.4.0) folosește uneltele de i18n construite-în, atunci când folosești versiuni mai vechi (<1.4.0) folosește angular-translate.

Performanță

  • Optimizează ciclul de digerare

    • Vezi doar cele mai vitale variabile. Atunci când trebuie să invoice ciclul $digest explicit (ar trebui să se întâmple doar în cazuri excepționale), invoc-o doar atunci când este necesar (de exemplu: atunci când folosești comunicare în timp real, nu cauza un ciclu $digest în fiecare mesaj primit).
    • Pentru conținutul care este inițializat doar o dată iar apoi niciodată schimbat, folosește veghetori o singură dată ca bindonce pentru versiuni mai vechi ale AngularJS sau legături o dată în AngularJS >=1.3.0.
      <div>
        {{ ::main.things }}
      </div>
      or
        <div ng-bind="::main.things"></div>

    După asta, niciun veghetor nu va fi creat pentru main.things și nicio schimbare a main.things nu va aduce la zi vederea.

    • Fă computațiile în $watch cât de simple posibile. A face computații greoaie și încete într-un singur $watch va înceta întreaga aplicației (ciclul $digest este făcut într-un singur fir datorită naturii de fir-singur al JavaScript).
    • Atunci când veghezi colecții, nu le veghea adânc atunci când nu este necesar. Mai bine folosești $watchCollection care produce o verificare superficială pentru egalitatea expresiei vegheate cu valoarea anterioară a expresiei evaluate.
    • Setează al treilea parametru în funcția $timeout ca fals pentru a sări peste ciclul $digest atunci când nicio variabilă nu e influențată de invocarea funcției de revenire $timeout.
    • Atunci când te ocupi de colecții mari, care se schimbă rar, folosește structuri de data imutabile.
  • Consideră descreșterea numărului de cereri de la rețea prin gruparea/arhivarea fișierelor șablon html în fișierul JavaScript principal, folosind grunt-html2js / gulp-html2js. Vezi aici și aici pentru detalii. Aceasta este util în mod special atunci când proiectul are un număr mare de șabloane html mici care pot fi parte din fișierul JavaScript principal (minificat sau gzip-at).

Contribuție

Deoarece scopul acestui ghid de stil este de a fi condus de comunitate, contribuțiile sunt foarte apreciate. De exemplu, poți contribui prin extinderea secțiune de Testare sau prin traducerea ghidului de stil în limba maternă.

Contributori

mgechev morizotter chatii2412 pascalockert yanivefraim ericguirbal
mgechev morizotter chatii2412 pascalockert yanivefraim ericguirbal
agnislav ray7551 mainyaa LeonardCModoran elfinxx tiagobarreto
agnislav ray7551 mainyaa LeonardCModoran elfinxx tiagobarreto
Xuefeng-Zhu SullyP giacomocusinato rubystream lukaszklis Spuffynism
Xuefeng-Zhu SullyP giacomocusinato rubystream lukaszklis Spuffynism
susieyy cironunes cavarzan guiltry MSafter mingchen
susieyy cironunes cavarzan guiltry MSafter mingchen
jmblog luixaviles andreasonny83 kuzzmi jabhishek adambabik
jmblog luixaviles andreasonny83 kuzzmi jabhishek adambabik
astalker clbn atodorov apetro valgreens bitdeli-chef
astalker clbn atodorov apetro valgreens bitdeli-chef
meetbryce unseen1980 cminhho dwmkerr kuzmeig1 dominickolbe
meetbryce unseen1980 cminhho dwmkerr kuzmeig1 dominickolbe
gsamokovarov grvcoelho yassirh bargaorobalo hermankan jesselpalmer
gsamokovarov grvcoelho yassirh bargaorobalo hermankan jesselpalmer
capaj johnnyghost jordanyee whoan nacyot mariolamacchia
capaj johnnyghost jordanyee whoan nacyot mariolamacchia
mischkl michaelmov kirstein mo-gr mortonfox cryptojuice
mischkl michaelmov kirstein mo-gr mortonfox cryptojuice
nktssh olafahn olov vorktanamobay QuietHeartThinkingFar raphaelfruneaux
nktssh olafahn olov vorktanamobay QuietHeartThinkingFar raphaelfruneaux
sahat ganchiku kaneshin imaimiami dooart thomastuts
sahat ganchiku kaneshin imaimiami dooart thomastuts
UrielMiranda vkarampinis grapswiz coderhaoxin giantray ntaoo
UrielMiranda vkarampinis grapswiz coderhaoxin giantray ntaoo
seyyah dchest
seyyah dchest