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

в 20:07, , рубрики: AngularJS, javascript, метки: ,

Как говорится в древней пословице – сколько людей столько и стилей написания кода. В сегодняшней статье я хотел бы расскрыть все особенности правильной настройки структуры 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: Я написал этот пост для того, чтобы ваше приложение можно было легко поддерживать и в дальнейшем, чтобы тот, кто будет дорабатывать ваше приложение понимал, что и как у вас там =)

Автор: xGromMx

Источник


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js