Grâce à une énorme quantité de précieuses sources, j'ai quelques recommandations générales pour la mise en œuvre de composants dans les applications AngularJS:
Contrôleur
Le contrôleur doit être juste un intermédiaire entre le modèle et la vue. Essayez de le rendre aussi mince que possible.
Il est fortement recommandé d' éviter la logique métier de contrôleur. Il doit être déplacé pour modèle.
Contrôleur peut communiquer avec d'autres contrôleurs à l'aide de la méthode d'invocation (possible lorsque les enfants veut communiquer avec un parent) ou $émettent, $diffusion et $sur les méthodes. Émis et diffusé les messages doivent être maintenus à un minimum.
Contrôleur doit se soucient pas de présentation ou de manipulation du DOM.
Essayez d' éviter imbriqués les contrôleurs. Dans ce cas, contrôleur de parent est interprété comme modèle. Injecter des modèles de services partagés de la place.
Champ d'application dans le contrôleur doit être utilisé pour la liaison de modèle avec vue et
l'encapsulation Modèle de Vue que pour le Modèle de Présentation modèle de conception.
Portée
Traiter portée en lecture seule dans les modèles et écrire uniquement dans les contrôleurs. Le but de la portée est de se référer au modèle, de ne pas être le modèle.
Lorsque vous faites bidirectionnel de liaison (ng-model) assurez-vous de ne pas lier directement à la portée des propriétés.
Modèle
Modèle en AngularJS est un singleton défini par le service.
Le modèle fournit un excellent moyen pour séparer les données et de les afficher.
Les modèles sont des candidats de choix pour les tests unitaires, comme ils ont généralement exactement une dépendance (une forme de manifestation de l'émetteur, dans le cas de l' $rootScope) et contiennent très testable domaine de la logique.
Modèle doit être considéré comme une mise en place de l'unité en question.
Elle est basée sur une seule responsabilité de principe. L'unité est une instance qui est responsable de son propre champ d'application de la logique que peut représenter la seule entité dans le monde réel et le décrire dans le monde de programmation en termes de données et de l'état.
Le modèle doit encapsuler les données de votre application et de fournir une API
pour accéder et manipuler des données.
Le modèle devrait être portable de sorte qu'il peut facilement être transporté sur similaires
application.
En isolant l'unité logique dans votre modèle, vous ont rendu plus facile
les localiser, de les mettre à jour et conserver.
Le modèle peut utiliser des méthodes plus générales sur les modèles globaux qui sont communes
pour l'ensemble de l'application.
Essayez d'éviter de composition d'autres modèles dans votre modèle à l'aide de l'injection de dépendance si elle n'est pas vraiment dépendant de la diminution de composants de couplage et l'augmentation de l'unité de la testabilité et de la convivialité.
Essayez d'éviter d'utiliser des écouteurs d'événement dans les modèles. Il les rend plus difficiles à tester et généralement tue des modèles en termes de la seule responsabilité de principe.
Mise En Œuvre Du Modèle
En tant que modèle doit encapsuler la logique en termes de données et de l'état, il devrait l'architecture de restreindre l'accès à ses membres ainsi nous pouvons garantir le couplage lâche.
La manière de le faire en application AngularJS est de la définir à l'aide de l'usine type de service. Cela va nous permettre de définir des propriétés privées et des méthodes très facile et aussi de retour publiquement accessibles dans le seul endroit qui le rendra vraiment lisible pour le développeur.
Un exemple:
angular.module('search')
.factory( 'searchModel', ['searchResource', function (searchResource) {
var itemsPerPage = 10,
currentPage = 1,
totalPages = 0,
allLoaded = false,
searchQuery;
function init(params) {
itemsPerPage = params.itemsPerPage || itemsPerPage;
searchQuery = params.substring || searchQuery;
}
function findItems(page, queryParams) {
searchQuery = queryParams.substring || searchQuery;
return searchResource.fetch(searchQuery, page, itemsPerPage).then( function (results) {
totalPages = results.totalPages;
currentPage = results.currentPage;
allLoaded = totalPages <= currentPage;
return results.list
});
}
function findNext() {
return findItems(currentPage + 1);
}
function isAllLoaded() {
return allLoaded;
}
// return public model API
return {
/**
* @param {Object} params
*/
init: init,
/**
* @param {Number} page
* @param {Object} queryParams
* @return {Object} promise
*/
find: findItems,
/**
* @return {Boolean}
*/
allLoaded: isAllLoaded,
/**
* @return {Object} promise
*/
findNext: findNext
};
});
La création de nouvelles instances
Essayez d'éviter d'avoir une usine qui renvoie une nouvelle mesure de fonction comme cela commence à décomposer l'injection de dépendance et de la bibliothèque va se comporter maladroitement, en particulier pour les tiers.
Une meilleure façon d'accomplir la même chose est d'utiliser de l'usine comme une API pour retourner une collection d'objets avec des méthodes getter et setter attaché à eux.
angular.module('car')
.factory( 'carModel', ['carResource', function (carResource) {
function Car(data) {
angular.extend(this, data);
}
Car.prototype = {
save: function () {
// TODO: strip irrelevant fields
var carData = //...
return carResource.save(carData);
}
};
function getCarById ( id ) {
return carResource.getById(id).then(function (data) {
return new Car(data);
});
}
// the public API
return {
// ...
findById: getCarById
// ...
};
});
Modèle Global
En général, essayez d'éviter de telles situations et la conception de vos modèles correctement donc il peut être injecté dans le contrôleur et utilisés dans votre point de vue.
Dans le cas particulier de certaines méthodes nécessitent l'accessibilité globale à l'intérieur de l'application.
Pour la rendre possible, vous pouvez définir la"commune de lapropriété $rootScope et le lier à commonModel lors de l'application de bootstrap:
angular.module('app', ['app.common'])
.config(...)
.run(['$rootScope', 'commonModel', function ($rootScope, commonModel) {
$rootScope.common = 'commonModel';
}]);
Toutes vos méthodes globales vivent à moins de ‘commun' de la propriété. C'est une sorte d' espace de noms.
Mais ne définit pas de méthodes directement dans votre $rootScope. Cela peut entraîner un comportement inattendu lorsqu'il est utilisé avec ngModel la directive au sein de votre portée de vue, généralement jonchent votre portée et conduit à la portée des méthodes de questions primordiales.
Ressources
Ressources vous permet d'interagir avec différentes sources de données.
Devrait être mis en œuvre en utilisant une seule responsabilité de principe.
Dans le cas particulier, il est réutilisable proxy HTTP/JSON points de terminaison.
Les ressources sont injectés dans les modèles et assurer la possibilité d'envoyer et de récupérer des données.
Ressources de mise en œuvre
Une usine qui crée un objet de ressource qui vous permet d'interagir avec RESTful côté serveur des sources de données.
Le retour de l'objet de la ressource a des méthodes d'action qui fournissent de haut niveau des comportements, sans la nécessité d'interagir avec le faible niveau de $service http.
Services
À la fois modèle et des ressources sont des services.
Des Services sont pas associés, faiblement couplé unités de fonctionnalités qui sont autonomes.
Les Services sont une fonctionnalité qui Angulaire apporte à côté client applications web côté serveur, où les services ont été couramment utilisés pendant une longue période.
Services Angulaire applications sont substituables les objets qui sont fixés ensemble à l'aide de l'injection de dépendance.
Angulaire est livré avec différents types de services. Chacun avec son propre cas d'utilisation. Veuillez lire Comprendre les Types de Service pour plus de détails.
Essayer de tenir compte des grands principes de l'architecture de services dans votre application.
En général, selon les Services Web Glossaire:
Un service est un résumé de la ressource qui représente une capacité de
de l'exécution de tâches qui forment un ensemble cohérent de fonctionnalités à partir du point de
vue de fournisseurs de entités et les demandeurs d'entités. Pour être utilisé, un
le service doit être réalisé par un fournisseur de béton de l'agent.
Côté Client, structure
En général partie client de l'application est découpée en modules. Chaque module doit être testable comme une unité.
Essayez de définir les modules en fonction de la fonctionnalité, de la fonctionnalité ou de la vue, et non pas par type.
Voir Misko de présentation pour plus de détails.
Composants du Module peut être classiquement regroupés par types, tels que les contrôleurs, les modèles, les vues, les filtres, directives, etc.
Mais le module en lui-même reste réutilisable, transférable et vérifiables.
Il est également beaucoup plus facile pour les développeurs de trouver certaines parties de code et de toutes ses dépendances.
Veuillez consulter le Code de l'Organisation dans les Grandes AngularJS et des Applications JavaScript pour plus de détails.
Un exemple de dossiers structurants:
|-- src/
| |-- app/
| | |-- app.js
| | |-- home/
| | | |-- home.js
| | | |-- homeCtrl.js
| | | |-- home.spec.js
| | | |-- home.tpl.html
| | | |-- home.less
| | |-- user/
| | | |-- user.js
| | | |-- userCtrl.js
| | | |-- userModel.js
| | | |-- userResource.js
| | | |-- user.spec.js
| | | |-- user.tpl.html
| | | |-- user.less
| | | |-- create/
| | | | |-- create.js
| | | | |-- createCtrl.js
| | | | |-- create.tpl.html
| |-- common/
| | |-- authentication/
| | | |-- authentication.js
| | | |-- authenticationModel.js
| | | |-- authenticationService.js
| |-- assets/
| | |-- images/
| | | |-- logo.png
| | | |-- user/
| | | | |-- user-icon.png
| | | | |-- user-default-avatar.png
| |-- index.html
Bon exemple de l'angulaire de l'application de structuration est mis en œuvre par angulaires-app - https://github.com/angular-app/angular-app/tree/master/client/src
Ceci est également considéré par l'application moderne générateurs - https://github.com/yeoman/generator-angular/issues/109