В разделе "Создать компоненты" на главной странице AngularJS приведен пример:
controller: function($scope, $element) {
var panes = $scope.panes = [];
$scope.select = function(pane) {
angular.forEach(panes, function(pane) {
pane.selected = false;
});
pane.selected = true;
}
this.addPane = function(pane) {
if (panes.length == 0) $scope.select(pane);
panes.push(pane);
}
}
Обратите внимание, что метод select
добавлен в $scope
, но метод addPane
добавлен в this
. Если я изменю его на $scope.addPane
, код сломается.
В документации говорится, что на самом деле это разница, но в ней не упоминается, в чем разница:
Предыдущие версии Angular (pre 1.0 RC) позволили использовать
this
взаимозаменяемо с методом$scope
, но это уже не так. Внутри методов, определенных в областиthis
и$scope
, взаимозаменяемы (angular устанавливаетthis
в$scope
), но не внутри внутри вашего конструктора контроллера.
Как работают this
и $scope
в контроллерах AngularJS?
"Как работают
this
и$scope
в контроллерах AngularJS?"
Короткий ответ:
this
this
является контроллером.$scope
, this
- это "область действия, когда функция была вызвана". Это может (или не может быть!) Быть $scope
, что функция определена. Таким образом, внутри функции this
и $scope
может не быть одинаковым.$scope
$scope
.$scope
.$scope
(и объекты родительской области, если прототипное наследование находится в игре) доступны из HTML/представления. Например, из ng-click
, фильтров и т.д.Длинный ответ:
Функция контроллера - это функция конструктора JavaScript. Когда функция конструктора выполняется (например, при загрузке представления), this
(то есть, "контекст функции" ) устанавливается в объект контроллера. Таким образом, в функции конструктора контроллера "tabs", когда создается функция addPane
this.addPane = function(pane) { ... }
он создается на объекте контроллера, а не на $scope. Представления не видят функцию addPane - они имеют доступ только к функциям, определенным в области $scope. Другими словами, в HTML это не сработает:
<a ng-click="addPane(newPane)">won't work</a>
После выполнения функции конструктора контроллера "tabs" мы имеем следующее:
Пунктирная черная линия указывает на прототипное наследование - изоляционная область прототипа наследует от Scope. (Он не прототипически наследуется от области действия, в которой директива встречается в HTML.)
Теперь функция ссылки на панели управления должна связываться с директивой tabs (что на самом деле означает, что она должна каким-то образом повлиять на вкладки, изолировать $scope). Можно использовать события, но другим механизмом является наличие указателя панели require
контроллера табуляции. (Кажется, нет механизма для директивы панели для require
вкладки $scope.)
Итак, это ставит вопрос: если у нас есть только доступ к контроллеру табуляции, как мы получим доступ к вкладкам, изолируем $scope (что мы действительно хотим)?
Ну, красная пунктирная линия - это ответ. Функция "scope" функции addPane() (я имею в виду область функций/закрытия JavaScript здесь) дает функции доступа к вкладкам изолировать $scope. I.e., addPane() имеет доступ к "вкладкам IsolateScope" на диаграмме выше из-за закрытия, которое было создано, когда была определена addPane(). (Если мы вместо этого определяем addPane() в объекте облака tabs $, директива панели не будет иметь доступа к этой функции, и, следовательно, у нее не будет возможности связываться с областью вкладок $.)
Чтобы ответить на другую часть вашего вопроса: how does $scope work in controllers?
:
В функциях, определенных в области $scope, this
устанавливается значение "$ scope", в котором/когда функция была вызвана ". Предположим, что мы имеем следующий HTML:
<div ng-controller="ParentCtrl">
<a ng-click="logThisAndScope()">log "this" and $scope</a> - parent scope
<div ng-controller="ChildCtrl">
<a ng-click="logThisAndScope()">log "this" and $scope</a> - child scope
</div>
</div>
И ParentCtrl
(Solely) имеет
$scope.logThisAndScope = function() {
console.log(this, $scope)
}
Щелчок по первой ссылке показывает, что this
и $scope
совпадают, так как "область действия, действующая при вызове функции", - это область, связанная с ParentCtrl
.
Щелчок по второй ссылке покажет, что this
и $scope
являются не тем же, поскольку "область действия, когда функция была вызвана", - это область, связанная с ChildCtrl
. Итак, здесь this
установлен на ChildCtrl
$scope
. Внутри метода $scope
по-прежнему остается ParentCtrl
$scope.
Я пытаюсь не использовать this
внутри функции, определенной в области $scope, так как это запутывает, на какую область видимости влияет, особенно учитывая, что ng-repeat, ng-include, ng-switch и директивы могут все создать свои собственные дочерние области.
Причиной "addPane" назначается это из-за директивы <pane>
.
Директива pane
выполняет require: '^tabs'
, которая помещает объект контроллера таблеток из родительской директивы в функцию ссылки.
addPane
присваивается this
, так что функция ссылки pane
может его видеть. Затем в функции pane
link, addPane
является просто свойством контроллера tabs
, и он просто tabsControllerObject.addPane. Таким образом, функция связывания с указателем панели может обращаться к объекту контроллера таблеток и, следовательно, обращаться к методу addPane.
Надеюсь, мои объяснения достаточно ясны. Это трудно объяснить.
Я просто прочитал довольно интересное объяснение различий между ними и растущее предпочтение прикреплять модели к контроллеру и псевдоним контроллера для привязки моделей к представлению. http://toddmotto.com/digging-into-angulars-controller-as-syntax/ - статья. Он не упоминает об этом, но при определении директив, если вам нужно поделиться чем-то между несколькими директивами и не хотеть службы (есть законные случаи, когда сервисы - это хлопот), тогда присоедините данные к родительскому директивному контроллеру. Служба $scope предоставляет множество полезных вещей, $watch является наиболее очевидным, но если все, что вам нужно, привязать данные к представлению, используя простой контроллер и "контроллер как" в шаблоне, отлично и, возможно, предпочтительнее.
В этом курсе (https://www.codeschool.com/courses/shaping-up-with-angular-js) они объясняют, как использовать "this" и многое другое.
Если вы добавляете метод к контроллеру с помощью метода "this", вы должны вызвать его в представлении с именем контроллера "точка" вашего свойства или метода.
Например, используя ваш контроллер в представлении, у вас может быть такой код:
<div data-ng-controller="YourController as aliasOfYourController">
Your first pane is {{aliasOfYourController.panes[0]}}
</div>
$scope
, поэтому спасибо, что упомянули его.
as
и this
так как это может помочь объяснить разницу?
Я рекомендую вам прочитать следующее сообщение: http://codetunnel.io/angularjs-controller-as-or-scope/
он очень хорошо описывает преимущества использования "Контроллера как" для отображения переменных по "$ scope".
Я знаю, что вы спросили конкретно о методах, а не переменных, но я думаю, что лучше придерживаться одной техники и быть в соответствии с ней.
Итак, по моему мнению, из-за проблемы с переменными, обсуждаемой в сообщении, лучше просто использовать технику "Контроллер как", а также применить ее к методам.
Предыдущие версии Angular (pre 1.0 RC) позволили вам использовать это взаимозаменяемо с методом $scope, но это уже не дело. Внутри методов, определенных в области действия this и $scope, взаимозаменяемый (angular устанавливает это значение в $scope), но не иначе внутри вашего конструктора контроллера.
Чтобы вернуть это поведение (кто-нибудь знает, почему он был изменен?), вы можете добавить:
return angular.extend($scope, this);
в конце вашей функции контроллера (при условии, что $scope был введен в эту функцию контроллера).
Это имеет приятный эффект от доступа к родительской области с помощью объекта контроллера, который вы можете получить с дочерним элементом require: '^myParentDirective'