Разделяй и властвуй или как сделать ваше приложение стуктурированным

от автора

Как говорится в древней пословице – сколько людей столько и стилей написания кода. В сегодняшней статье я хотел бы расскрыть все особенности правильной настройки структуры AngularJS.
Как в любом приложении у нас должна быть точка входа, начальная точка откуда будет стартовать наше приложение. За частую я использую просто app. В этом файле, который не плохо было бы назвать main.js мы напишем такой код:

(function(ng) { 	var app = ng.app('app', []);  	// This should be your configuration like a routeProvider or etc. 	 	return app; })(angular); 

Также этот модуль будет в будущем включать остальные модули за счет dependency injection.
Что же начало положено и не плохо было бы определиться со структурой приложения. Определим определенные сущности нашего приложения. Создадим папки: animations, controllers, factories, directives. По сути, сейчас мы сформируем тот подход, что используется в Java package.
Итак, каждая из директорий что мы создали должна также содержать свои точки входа, опять же таки именуемые main.js. Для примера рассмотрим директорию с контроллерами. В main.js прописываем такой код:

(function(ng) { 	var app = ng.app('app.controllers', []); 	 	return app; })(angular); 

Как можно заметить, этот модуль будет отвечать за внедрение контроллеров, которые мы объявим ниже. Также теперь мы можем включить этот модуль в зависимости основного модуля, который примет вид:

(function(ng) { 	var app = ng.app('app', ['app.controllers']);  	// This should be your configuration like a routeProvider or etc. 	 	return app; })(angular); 

Теперь опишем пару контроллеров для нашего приложения, чтобы показать как мы можем использовать. Есть определенные соглашения с названием контроллеров, а именно в стиле camel-case как класс. Чтоже создадим файл в директории controllers MainCtrl.js, который будем содержать нашу логику контроллера. Его содержимое будет примерно такое:

(function(ng) { 	var app = ng.app('app.controllers.MainCtrl', []);  	var MainCtrl = function($scope) { 		var localScope = { 			message: 'Message', 			list: [1,2,3,4,5,6] 		};  		ng.extend($scope, localScope); 	};  	app.controller('MainCtrl', ['$scope', MainCtrl]); 	 	return app; })(angular); 

Давайте разберем, почему такой подход имеет право на жизнь. Как и раньше у нас объявлен модуль, который будет встроен в зависимости основного модуля контроллеров. Сам код контроллера вынесен в отдельную функцию. После этого он включен как контроллер и использована полная запись объявления контроллера для того чтобы он не был сломан после минимизации и обфускации. Как можно заметить, в нашем контроллере создана локальная переменная как localScope. Для чего это сделано? При небольшом колличестве переменных в $scope это особо не заметно, но когда их становится много, кода становится немного не читабельным и поэтому я просто взял технику расширения основного $scope через метод angularjs extend. Как по мне, такой способ красив, лаконичен и довольно читаем. Также добавим наш контроллер в зависимоть нашего основного модуля для контроллеров. Его код будет таким:

(function(ng) { 	var app = ng.app('app.controllers', ['app.controllers.MainCtrl']);  	return app; })(angular); 

По такому принципу мы будем строить и другие зависимоти для директив, фабрик и так далее. Как по мне, такой подход дает полное понимание вашего приложения, его структура сразу становится видна и очень просто модернизировать, добавляя новые контроллеры, сервисы, директивы и прочее.

В заключение я хотел бы поговорить немного о контроллерах, вернее о новом синтаксисе “as”
Если мы не хотим чтобы наши переменные или же какие-то функции были observable. То мы можем полноценно использовать такой подход:

(function(ng) { 	var app = ng.app('app.controllers.MainCtrl', []);  	var MainCtrl = function($scope, $log) { 		var localScope = { 			message: 'Message', 			list: [1,2,3,4,5,6] 		};  		this.nonObservableVar = { 			one: 1, 			two: 2 		};  		this.logger = function(obj) { 			$log.info(obj); 		};  		ng.extend($scope, localScope); 	};  	app.controller('MainCtrl', ['$scope', '$log', MainCtrl]); 	 	return app; })(angular); 

И в нашем view использовать такой код:

<div ng-controller="MainCtrl as main"> 	<div ng-click="main.logger('Test for a one value')">{{ main.nonObservableVar.one }}</div> 	<div ng-click="main.logger('Test for a two value')">{{ main.nonObservableVar.two }}</div> </div> 

Что это нам дает? Ну одно из преимуществ, то что тут нет angular watcher’ов. Это ускоряет наше приложение, также дает возможность в вложенных контроллерах использовать контекст родительских контроллеров, что дает возможность более гибко строить наше приложение. Этот способ очень прост в использовании. Как и раньше мы также можем смешивать переменные контроллера с переменными $scope для возможности использования $watch, $apply, etc.

Если интересно, буду дальше писать про angular и как на нем строить красивые и структурированные приложения. В плане написать статью про использования angularjs с requirejs и прекрасной фичей requirejs – пакеты.
Оставляйте свои отзывы в комменариях.
PS: Я написал этот пост для того, чтобы ваше приложение можно было легко поддерживать и в дальнейшем, чтобы тот, кто будет дорабатывать ваше приложение понимал, что и как у вас там =)

ссылка на оригинал статьи http://habrahabr.ru/post/215273/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *