Как перейти с jQuery на AngularJS: думаем по-новому
Главное отличие: AngularJS — это не библиотека для манипуляции DOM, а фреймворк для построения приложений
Ваша проблема типична для всех, кто приходит из jQuery. Ключевой сдвиг в мышлении: вы не управляете DOM напрямую. Вместо этого вы описываете состояние приложения (данные в $scope) и говорите AngularJS: "Вот шаблон, вот данные — свяжи их".
Давайте разберём ваш пример с формой и кнопкой "Добавить". Вот как это должно выглядеть в AngularJS:
<!-- HTML шаблон (view) -->
<div ng-app="myApp" ng-controller="MainController">
<input type="text" ng-model="newItemName" placeholder="Введите название">
<button ng-click="addItem()">Добавить</button>
<ul>
<li ng-repeat="item in items">{{ item.name }}</li>
</ul>
</div>
<!-- JavaScript (controller) -->
<script>
var app = angular.module('myApp', []);
app.controller('MainController', function($scope) {
// Состояние приложения — массив объектов
$scope.items = [];
// Функция, которая будет вызвана по ng-click
$scope.addItem = function() {
// Проверяем, что поле не пустое
if ($scope.newItemName && $scope.newItemName.trim()) {
// Добавляем новый элемент в массив
$scope.items.push({
name: $scope.newItemName.trim()
});
// Очищаем поле ввода
$scope.newItemName = '';
}
};
});
</script>
Почему это работает иначе, чем в jQuery?
- ng-model создаёт двустороннюю привязку данных: изменения в input автоматически обновляют $scope.newItemName, и наоборот.
- ng-repeat автоматически перерисовывает список при изменении массива $scope.items. Вам не нужно вручную добавлять/удалять DOM-элементы.
- ng-click привязывает событие клика к функции $scope.addItem(). Вам не нужны селекторы и .on() — AngularJS сам знает, какой контроллер обрабатывает этот участок DOM.
Ваш главный ментальный сдвиг: думайте о данных, а не о DOM. Вы работаете с моделью (данные в $scope), а AngularJS сам синхронизирует её с представлением (HTML). Если данные изменились — DOM обновится автоматически.
Почему ваш код не работал?
Скорее всего, вы пытались напрямую обращаться к DOM внутри контроллера:
// ❌ НЕПРАВИЛЬНО (jQuery-мышление)
$('#addBtn').on('click', function() { ... });
В AngularJS контроллер не должен знать о DOM. Вся работа с DOM — это задача директив (ng-click, ng-model, ng-repeat и кастомных директив).
Ещё одна частая ошибка: попытка использовать jQuery-методы внутри контроллера для обновления DOM. Этого делать нельзя — это нарушает архитектуру MVVM и может привести к багам, когда AngularJS не узнает об изменениях.
Пошаговая инструкция для перестройки мышления:
- Сначала опишите данные — что вы хотите показать на странице? Создайте $scope.объекты и массивы.
- Потом опишите поведение — какие действия может совершить пользователь? Создайте $scope.функции для этих действий.
- Затем создайте шаблон — используйте директивы (ng-repeat, ng-if, ng-show, ng-class) для связывания данных с HTML.
- Забудьте про id и классы для доступа к элементам. В AngularJS вы работаете через ng-model, ng-click, ng-bind и другие директивы.
Попробуйте переписать вашу задачу с загрузкой списка через API в AngularJS-стиле:
app.controller('ItemController', function($scope, $http) {
// 1. Данные
$scope.items = [];
$scope.loading = false;
// 2. Поведение
$scope.loadItems = function() {
$scope.loading = true;
$http.get('/api/items')
.then(function(response) {
$scope.items = response.data;
$scope.loading = false;
})
.catch(function(error) {
$scope.loading = false;
console.error('Ошибка:', error);
});
};
});
Обратите внимание: мы не трогаем DOM. Просто обновляем $scope.items, и AngularJS сам перерисовывает список.
<<Дополнение: используйте сервисы для бизнес-логики и директивы для повторного использования
Когда вы освоите базовый сдвиг "данные вместо DOM", следующий шаг — научиться правильно организовывать код. В jQuery вы часто пишете всё в одном скрипте. В AngularJS код разделяется на:
- Контроллеры — только связывают данные и шаблон (не должны содержать логику запросов к API).
- Сервисы/Фабрики — содержат бизнес-логику, запросы к серверу, работу с localStorage и т.д.
- Директивы — для переиспользуемых компонентов UI (например, кастомный дропдаун или модальное окно).
Пример правильной структуры для вашей задачи с формой:
// Сервис для работы с данными
app.service('ItemService', function($http) {
this.getItems = function() {
return $http.get('/api/items');
};
this.addItem = function(name) {
return $http.post('/api/items', { name: name });
};
});
// Контроллер использует сервис
app.controller('MainController', function($scope, ItemService) {
$scope.items = [];
$scope.loadItems = function() {
ItemService.getItems().then(function(res) {
$scope.items = res.data;
});
};
$scope.addItem = function() {
ItemService.addItem($scope.newItemName).then(function() {
$scope.loadItems(); // перезагружаем список после добавления
$scope.newItemName = '';
});
};
// Загружаем данные при старте
$scope.loadItems();
});
Такой подход делает код тестируемым, модульным и легко поддерживаемым. Помните: в AngularJS вы строите архитектуру приложения, а не просто "оживляете" HTML.