В разделе «Создание компонентов» на домашней странице 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 (до 1.0 RC) позволяли вам использовать метод
this
взаимозаменяемо$scope
, но это уже не так. Внутри методов , определенных на объемthis
и$scope
являются взаимозаменяемыми (угловые наборыthis
в$scope
), но не иначе внутри конструктора контроллера.
Как работает this
и $scope
работает в контроллерах AngularJS?
angularjs
angularjs-scope
this
Алексей Боронин
источник
источник
Ответы:
Краткий ответ :
this
this
это контроллер.$scope
вызывается функция, определенная для объекта,this
это «область действия, когда функция была вызвана». Это может (или не может!) Быть тем$scope
, на котором определена функция. Итак, внутри функцииthis
и не$scope
могут быть одинаковыми.$scope
$scope
объект.$scope
.$scope
объекте (и родительские объекты области, если прототипное наследование находится в игре) доступны из HTML / представления. Например, отng-click
, фильтры и т. Д.Длинный ответ :
Функция контроллера - это функция конструктора JavaScript. Когда выполняется функция конструктора (например, когда загружается представление)
this
(то есть «контекст функции») устанавливается на объект контроллера. Так в функции конструктора контроллера «вкладки» при создании функции addPaneон создается на объекте контроллера, а не на $ scope. Представления не могут видеть функцию addPane - они имеют доступ только к функциям, определенным в $ scope. Другими словами, в HTML это не будет работать:
После выполнения функции конструктора контроллера «tabs» имеем следующее:
Пунктирная черная линия указывает на наследование прототипа - область изолята, прототипно наследуемая от Scope . (Он не наследуется по прототипу от области действия, в которой директива встречалась в HTML.)
Теперь функция link директивы pane хочет связаться с директивой tabs (что на самом деле означает, что она должна каким-то образом влиять на вкладки, изолируя $ scope). События могут быть использованы, но другой механизм должен иметь директиву pane
require
контроллера tabs. (По-видимому, не существует механизма для директивы панели дляrequire
вкладок $ scope.)Итак, напрашивается вопрос: если у нас есть доступ только к контроллеру вкладок, как нам получить доступ к вкладкам, изолирующим $ scope (что мы действительно хотим)?
Ну, красная пунктирная линия - это ответ. «Область» функции addPane () (я имею в виду область / замыкания функции JavaScript здесь) дает функции доступ к вкладкам, изолирующим область $. То есть addPane () имеет доступ к «вкладкам IsolateScope» на диаграмме выше из-за замыкания, которое было создано при определении addPane (). (Если бы мы вместо этого определили addPane () на объекте $ scope вкладок, директива pane не будет иметь доступа к этой функции, и, следовательно, не будет иметь возможности связаться с вкладками $ scope.)
Чтобы ответить на другую часть вашего вопроса
how does $scope work in controllers?
:Внутри функций, определенных в $ scope,
this
устанавливается значение «действительная область $, где / когда была вызвана функция». Предположим, у нас есть следующий HTML:И
ParentCtrl
(только) имеетНажатие на первую ссылку покажет , что
this
и$scope
то же, так как « сфера действует , когда функция была вызвана » является областью , связанная сParentCtrl
.При нажатии на вторую ссылку покажет ,
this
и$scope
это не то же самое, так как « сфера действует , когда функция была вызвана » является областью , связанный сChildCtrl
. Итак, здесьthis
установлено значениеChildCtrl
s$scope
. Внутри метода$scope
все еще находитсяParentCtrl
область действия $.скрипка
Я стараюсь не использовать
this
внутри функции, определенной в $ scope, так как становится непонятно, какая область $ затрагивается, особенно с учетом того, что ng-repeat, ng-include, ng-switch и директивы могут создавать свои собственные дочерние области.источник
Причина, по которой этому назначается addPane, связана с
<pane>
директивой.pane
Директива делаетrequire: '^tabs'
, что ставит вкладки контроллера объекта из родительской директивы, в функции связи.addPane
назначаетсяthis
так, чтобыpane
функция ссылки могла его видеть. Тогда вpane
функции ссылкиaddPane
это просто свойствоtabs
контроллера, а это просто tabsControllerObject.addPane. Таким образом, функция связывания директивы панели может обращаться к объекту контроллера вкладок и, следовательно, к методу addPane.Надеюсь, мои объяснения достаточно ясны ... это сложно объяснить.
источник
Я только что прочитал довольно интересное объяснение различий между ними и растущего предпочтения присоединять модели к контроллеру и псевдоним контроллера для привязки моделей к представлению. http://toddmotto.com/digging-into-angulars-controller-as-syntax/ это статья.
Он не упоминает об этом, но при определении директив, если вам нужно разделить что-то между несколькими директивами и не хотите, чтобы сервис (есть законные случаи, когда сервисы доставляют неудобства), тогда присоедините данные к контроллеру родительской директивы.
$scope
Служба предоставляет множество полезных вещей,$watch
будучи наиболее очевидными, но если все , что вам нужно привязать данные к представлению, используя обычный контроллер и контроллер «как» в шаблоне хорошо и , возможно , предпочтительнее.источник
Я рекомендую вам прочитать следующий пост: AngularJS: "Controller as" или "$ scope"?
Он очень хорошо описывает преимущества использования «Controller as» для выставления переменных над «$ scope».
Я знаю, что вы спрашивали конкретно о методах, а не о переменных, но я думаю, что лучше придерживаться одного метода и придерживаться его.
Поэтому, на мой взгляд, из-за проблемы с переменными, обсуждавшейся в посте, лучше просто использовать технику «Контроллер как», а также применить ее к методам.
источник
В этом курсе ( https://www.codeschool.com/courses/shaping-up-with-angular-js ) они объясняют, как использовать «это» и многие другие вещи.
Если вы добавляете метод к контроллеру через метод «this», вы должны вызывать его в представлении с именем контроллера «dot» вашего свойства или метода.
Например, используя ваш контроллер в представлении, вы можете иметь такой код:
источник
$scope
, так что спасибо, что упомянули его.as
иthis
как он может помочь объяснить разницу?$scope
никогда не упоминалось, я научился использовать толькоthis
в контроллерах. Проблема в том, что, когда вы начинаете обрабатывать обещания в вашем контроллере, у вас возникает много проблем с ссылками,this
и вам приходится начинать делать что-то вродеvar me = this
ссылки на модельthis
из функции возврата обещания. Поэтому из-за этого я все еще не понимаю, какой метод мне следует использовать,$scope
илиthis
.var me = this
или.bind(this)
когда вы делаете обещания, или другие тяжелые вещи закрытия. Это не имеет ничего общего с Angular.ng-controller="MyCtrl as MC"
это эквивалентно установке$scope.MC = this
самого контроллера - он определяет экземпляр (этого) MyCtrl в области видимости для использования в шаблоне через{{ MC.foo }}
Чтобы вернуть это поведение (кто-нибудь знает, почему оно было изменено?), Вы можете добавить:
в конце вашей функции контроллера (при условии, что $ scope был введен в эту функцию контроллера).
Это имеет хороший эффект наличия доступа к родительской области через объект контроллера, который вы можете получить в child с
require: '^myParentDirective'
источник
$ scope имеет другое «this», чем контроллер «this». Таким образом, если вы поместите console.log (this) внутри контроллера, он даст вам объект (controller), а this.addPane () добавляет метод addPane к объекту контроллера. Но $ scope имеет различную область видимости, и $ scope.methodName () должен принимать все методы в своей области видимости.
this.methodName()
внутри контроллера означает добавить методы внутри объекта контроллера.$scope.functionName()
в HTML и внутриВставьте этот код в ваш редактор и откройте консоль, чтобы увидеть ...
источник