Avatar ·

Как перейти с jQuery на AngularJS: думаем по-новому

Всем привет! Я начинающий фронтенд-разработчик, и у меня серьёзная проблема. Я долгое время писал на jQuery, и теперь пытаюсь освоить AngularJS, но мой мозг просто отказывается перестраиваться. В jQuery я привык всё делать руками: найти элемент через $('selector'), повесить обработчик, изменить DOM напрямую. Например, чтобы обновить список, я пишу: ```javascript // jQuery стиль $('#loadBtn').on('click', function() { $.get('/api/items', function(data) { var list = $('#itemList'); list.empty(); data.forEach(function(item) { list.append('
  • ' + item.name + '
  • '); }); }); }); ``` В AngularJS я пытаюсь делать то же самое, но получается каша из $scope, директив и сервисов. Я постоянно ловлю себя на мысли: "Где мне взять этот элемент? Как привязать событие? Почему данные не обновляются в шаблоне?" Конкретный пример: у меня есть форма ввода и кнопка "Добавить". В jQuery я просто беру значение из input, создаю новый элемент и вставляю его в DOM. В AngularJS я создал контроллер, добавил $scope.items = [], написал функцию addItem(), но когда я вызываю её через ng-click, ничего не происходит. Я уже целый день гуглю, но все примеры слишком абстрактные. Подскажите, как правильно мыслить при работе с AngularJS? Как избавиться от привычки "ручного" управления DOM? Может быть, есть какой-то ментальный сдвиг, который нужно сделать? Спасибо! <<>>

    Главное отличие: 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 не узнает об изменениях.

    Пошаговая инструкция для перестройки мышления:

    1. Сначала опишите данные — что вы хотите показать на странице? Создайте $scope.объекты и массивы.
    2. Потом опишите поведение — какие действия может совершить пользователь? Создайте $scope.функции для этих действий.
    3. Затем создайте шаблон — используйте директивы (ng-repeat, ng-if, ng-show, ng-class) для связывания данных с HTML.
    4. Забудьте про 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.