Что такое `$scope` в AngularJS? Учебное пособие с примером.

⚡ Умное резюме

В AngularJS `$Scope` — это встроенный объект, который связывает контроллер с его представлением. На этой странице объясняется создание области видимости, функции поведения, иерархия родительских и дочерних элементов, отличие от `$rootScope` и то, как циклы обновления (digest cycles) обновляют привязки.

  • 🔗 Связывающая роль: Переменная `$scope` переносит переменные-члены из контроллера в представление, поэтому шаблоны отображают данные, не затрагивая DOM напрямую.
  • ⚙️ Функции поведения: Прикрепляйте функции к переменной $scope, когда представление должно реагировать на щелчки мыши, изменения во входных данных или другие события пользователя.
  • ???? Иерархия областей действия: Директивы, такие как ng-controller и ng-repeat, создают дочерние области видимости, которые отражают DOM-дерево приложения.
  • 🌍 $rootScope reach: Для каждого приложения существует один объект $rootScope, который ведёт себя как глобальный объект, доступный для чтения каждому дочернему объекту.
  • 🔍 Цикл переваривания: $watch регистрирует слушатели, $apply переходит в контекст выполнения AngularJS, а $digest сравнивает значения до тех пор, пока модель не стабилизируется.
  • 🚀 Привычка к эффективности: Используйте выражения для отслеживания изменений (watch expressions) с минимальными затратами ресурсов, избегайте доступа к DOM внутри них и вызывайте `$destroy` для областей видимости, которые больше не нужны.

Что такое $Scope в AngularJS?

Что такое $scope в AngularJS?

$scope в AngularJS — это встроенный объект, который по сути связывает «контроллер» и «представление». Можно определить переменные-члены в области действия внутри контроллера, к которым затем может получить доступ представление.

Каждый контроллер в AngularJS Приложение получает собственный экземпляр `$scope` через внедрение зависимостей. Всё, что вы прикрепляете к этому объекту, становится видимым для шаблона, управляемого контроллером, поэтому `$scope` ведёт себя как общая модель данных, которая находится между вашими компонентами. JavaЛогика скрипта и ваша HTML-разметка.

Рассмотрим пример ниже:

$scope в AngularJS

angular.module('app',[]).controller('HelloWorldCtrl',
	function($scope)
	{
		$scope.message = "Hello World"
	});

Code Объяснение:

  1. Имя модуля — «приложение».
  2. Имя контроллера — «HelloWorldCtrl».
  3. Объект Scope — это основной объект, который используется для передачи информации от контроллера к представлению.
  4. Переменная-член добавлена ​​в объект области

⚠️ Синтаксическое предупреждение: .controller() Метод принимает два аргумента: имя контроллера и фабричную функцию, поэтому между ними должна быть запятая. 'HelloWorldCtrl' и function($scope)Отсутствие запятой приводит к ошибке. Uncaught SyntaxError до того, как AngularJS запустится.

Один контроллер и одно представление — это лишь половина картины. В реальных приложениях контроллеры вложены друг в друга, списки повторов повторяются, а виджеты используются повторно, что означает существование нескольких областей видимости одновременно.

Как работают иерархия областей видимости и наследование в AngularJS

Каждое приложение AngularJS имеет ровно одну корневую область видимости и может иметь любое количество дочерних областей видимости. Директивы создают эти дочерние области видимости и прикрепляют их к элементу DOM, который они декорируют, так что дерево областей видимости отражает структуру отображаемой страницы.

Когда AngularJS вычисляет такое выражение, как... {{siteName}}Сначала выполняется поиск этого свойства в области видимости, прикрепленной к элементу. Если свойство отсутствует, поиск переходит в родительскую область видимости и продолжается до тех пор, пока не достигнет корневой области видимости. JavaРазработчики скриптов знают это поведение как прототипное наследование, и дочерние области видимости наследуют от своих родителей именно таким образом.

В приведенном ниже примере один контроллер вложен в другой, что позволяет наблюдать за процессом наследования.

<div ng-app="scopeDemo">
    <div ng-controller="ParentCtrl">
        Parent scope value: {{siteName}}
        <div ng-controller="ChildCtrl">
            Child reads parent value: {{siteName}}
            Child own value: {{lesson}}
        </div>
    </div>
</div>

<script type="text/javascript">
    var app = angular.module("scopeDemo", []);

    app.controller("ParentCtrl", function($scope) {
        $scope.siteName = "Guru99";
    });

    app.controller("ChildCtrl", function($scope) {
        $scope.lesson = "AngularJS Scope";
    });
</script>

Code Объяснение:

  1. ParentCtrl определяет siteName в рамках своей собственной сферы деятельности.
  2. ChildCtrl никогда не определяет siteNameОднако внутренний div по-прежнему выводит сообщение. Guru99 потому что поиск обращается к родительской области видимости.
  3. lesson Этот элемент существует только в дочерней области видимости, поэтому родительский div не может его прочитать.

Какие директивы создают новую область видимости?

  • ng-controller: Создает дочернюю область видимости для элемента, на котором она размещена.
  • ng-repeat: Создает одну дочернюю область видимости на каждую итерацию, поэтому каждая строка может содержать разные значения для одного и того же выражения.
  • Пользовательские директивы: может запросить дочерний сегмент или изолировать Область видимости, которая намеренно не наследует от своего родителя.
  • Директивы компонентов: все, что зарегистрировано в .component() Вспомогательная функция всегда получает изолированную область видимости.

Поскольку дочерние области видимости считывают данные вверх, разработчики часто задаются вопросом, где находится вершина этой цепочки. Этот объект верхнего уровня называется $rootScope.

$scope против $rootScope: в чем разница?

AngularJS $rootScope $rootScope — это область видимости для всего приложения. В приложении может быть только один $rootScope, и он используется как глобальная переменная. Каждый $scope является дочерней областью видимости, а $rootScope — это родительский объект на вершине дерева. В таблице ниже приведено сравнение этих двух объектов.

Аспект $ scope $rootScope
Количество экземпляров на одно приложение Много, по одному на каждый контроллер или директиву, создающую область действия. Ровно один
Созданный Директивы, такие как ng-controller и ng-repeat Инжектор во время загрузки приложения
Прозрачность Его собственная стихия и все его потомки Каждая область действия в приложении
Типичное использование Данные и поведение для одного представления или одной строки списка. Значения, характерные для всего приложения, например, информация о вошедшем в систему пользователе.
Основной риск Значения становятся недоступными за пределами филиала. Конфликты имен и скрытая взаимосвязь, как, например, в случае глобальных переменных.

Используйте `$rootScope` с осторожностью. Всё, что там находится, существует на протяжении всего приложения и доступно для чтения повсюду, поэтому для глобального состояния обычно безопаснее использовать общий сервис. $rootScope reference Отображает полный список API.

Знание того, где хранятся данные, — это половина работы. Другая половина — это обучение системы тому, как реагировать на действия пользователя.

Настройка или добавление поведения в AngularJS

Чтобы реагировать на события или выполнять какие-либо вычисления/обработки в представлении, мы должны обеспечить поведение области видимости.

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

Давайте посмотрим на примере, как мы можем этого добиться.

Настройка или добавление поведения

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta chrset="UTF 8">
    <title>Guru99</title>     
</head>  
<body ng-app="DemoApp">
<h1> Guru99 Global Event</h1>
<script src="https://code.angularjs.org/1.6.9/angular.js"></script>
<div ng-controller="DemoController">
	{{fullName("Guru","99")}}
</div>
<script type="text/javascript">  
	var app = angular.module("DemoApp", []);
	app.controller("DemoController", function($scope) {
    
    $scope.fullName=function(firstName,lastname){
		return firstName + lastname;
		}
	} );
</script> 

</body>  
</html>

Code Объяснение:

  1. Мы создаем поведение под названием «fullName». Это поведение представляет собой функцию, которая принимает 2 параметра (имя, фамилия).
  2. Затем поведение возвращает объединение этих двух параметров.
  3. В представлении мы вызываем поведение и передаем 2 значения типа «Guruи «99», которые передаются в качестве параметров в поведение.

Если команда выполнена успешно, при запуске кода в браузере будет отображен следующий вывод.

Выход:

Настройка или добавление поведения

В браузере вы увидите объединение обоих значений. Guru & 99, которые были переданы в поведение в контроллер.

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

Почему важны Scope Watchers и цикл дайджеста

AngularJS поддерживает соответствие представления области видимости с помощью проверки изменений (dirty check), а не через события изменения (change events). Этот процесс обеспечивают три API для областей видимости:

  • $watch: Регистрирует слушателя для выражения. Интерполяции, такие как... {{fullName}} регистрировать наблюдателей для вас во время связывания шаблонов.
  • $apply: Эта функция входит в контекст выполнения AngularJS, выполняет ваш код, а затем запускает дайджест. Она необходима только внутри пользовательских обработчиков событий или обработчиков событий сторонних библиотек, поскольку встроенные директивы уже вызывают её.
  • $digest: Этот процесс обходит каждый наблюдатель в $rootScope и его дочерних элементах, сравнивая текущее значение с предыдущим, и повторяет это до тех пор, пока модель не перестанет меняться.

Поскольку дайджест может выполняться в несколько проходов, выражения наблюдения должны оставаться недорогими. Избегайте доступа к DOM внутри них, поскольку чтение DOM на порядки медленнее, чем чтение JavaСвойство скрипта.

Глубина запоминания также влияет на стоимость. Запоминание по эталонному значению — самый быстрый способ, и результат заметен только тогда, когда заменена вся величина. $watchCollection Отслеживание по значению позволяет отслеживать добавление, удаление или изменение порядка элементов внутри массива или объекта. Отслеживание по значению проходит по вложенной структуре при каждом обновлении и является наиболее ресурсоемким вариантом, поэтому используйте его в последнюю очередь.

Часто задаваемые вопросы (FAQ)

Изолированная область видимости не наследует прототипически от родительского элемента. Директивы компонентов, созданные с помощью вспомогательной функции `.component()`, всегда получают её, что обеспечивает независимость многократно используемых виджетов от окружающего контроллера и блокирует случайное чтение свойств родительского элемента.

$emit отправляет событие области видимости вверх через родительские области видимости к $rootScope, а $broadcast отправляет его вниз к каждой дочерней области видимости. Оба события принимаются с помощью $on. Используйте $broadcast экономно, поскольку он посещает каждую дочернюю область видимости.

Вызовите scope.$destroy(), когда дочерняя область видимости больше не нужна. Это остановит распространение дайджеста в область видимости и позволит сборщику мусора освободить свои модели. Также отмените регистрацию наблюдателей, управляемых вручную, вызвав функцию, которую возвращает $watch.

Помощники, такие как Второй пилот GitHub Быстро создают шаблонный код, но при этом всё равно допускают ошибки, например, пропущенную запятую при регистрации контроллера. Каждый сгенерированный фрагмент кода проверяется на соответствие официальным стандартам. Документация по области видимости AngularJS.

Искусственный интеллект-помощники сопоставляют свойства `$scope` с полями класса компонента и переписывают логику `$watch` в виде сигналов или потоков RxJS. Используйте их в паре с официальными инструментами. Угловой необходимо документировать и запускать модульные тесты, поскольку сгенерированные преобразования часто не учитывают поиск в унаследованной области видимости.

Подведем итог этой публикации следующим образом: