«Как
blockquote>this
и$scope
работают в контроллерах AngularJS?»Короткий ответ:
this
Когда вызывается функция конструктора контроллера,this
- контроллер. Когда вызывается функция, определенная на объекте$scope
,this
является «областью действия, когда функция была вызвана». Это может (или не может быть!) Быть$scope
, что функция определена. Таким образом, внутри функцииthis
и$scope
могут быть не одинаковыми.$scope
Каждый контроллер имеет ассоциированный объект$scope
. Функция контроллера (конструктора) отвечает за настройку свойств модели и функций / поведения на ее ассоциированном$scope
. Только методы, определенные на этом объекте$scope
(и родительские объекты области, если прототипическое наследование находится в игре) доступны из HTML / view. Например, изng-click
, фильтров и т. Д.Длинный ответ:
Функция контроллера - это функция JavaScript-конструктора. Когда функция конструктора выполняется (например, при загрузке представления),
this
(то есть «контекст функции») устанавливается в объект контроллера. Таким образом, в функции конструктора контроллера «tabs», когда создается функция addPanethis.addPane = function(pane) { ... }
, она создается на объекте контроллера, а не на $ scope. Представления не видят функцию addPane - они имеют доступ только к функциям, определенным в области $ scope. Другими словами, в HTML это не сработает:
<a ng-click="addPane(newPane)">won't work</a>
После выполнения функции конструктора контроллера «tabs» мы имеем следующее:
[/g4]
Пунктирная черная линия указывает на прототипное наследование - объем выделения, который прототипически наследуется из Scope . (Это не прототипно наследует область действия, в которой эта директива встречается в HTML.)
Теперь функция ссылки директивы панели хочет связываться с директивой tabs (что на самом деле означает, что она должна влиять вкладки каким-то образом изолируют $ scope). Можно использовать события, но другим механизмом является наличие указателя панели
require
контроллера табуляции. (Кажется, нет механизма для директивы панели дляrequire
вкладки $ scope.)Итак, это ставит вопрос: если у нас есть только доступ к контроллеру вкладок, как мы получаем доступ на вкладках изолировать $ scope (что мы действительно хотим)?
Ну, красная пунктирная линия - это ответ. Функция «scope» функции addPane () (я имею в виду область действия / закрытие функции JavaScript здесь) дает функции доступа к вкладкам изолировать $ scope. I.e., addPane () имеет доступ к «вкладкам IsolateScope» на диаграмме выше из-за закрытия, которое было создано, когда была определена addPane (). (Если мы вместо этого определяем addPane () в объекте облака tabs $, директива панели не будет иметь доступа к этой функции, и, следовательно, у нее не будет возможности связываться с областью вкладок $.)
To ответьте на другую часть вашего вопроса:
how does $scope work in controllers?
:В функциях, определенных в области $ scope,
this
установлено значение «область действия, в которой / когда функция была вызвана». Предположим, что у нас есть следующий 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
по-прежнему является [scope]ParentCtrl
.Я пытаюсь не использовать
this
внутри функция, определенная в области $ scope, так как она запутывает, на какой объект влияет область видимости, особенно учитывая, что ng-repeat, ng-include, ng-switch и директивы могут создавать собственные дочерние области.
$ scope имеет другое «это», а затем контроллер «это». Таким образом, если вы ввели контроллер console.log (this) внутри контроллера, он дает вам объект (контроллер), а this.addPane () добавляет метод AddPane к объект контроллера. Но область $ имеет разный объем, и весь метод в своей области должен быть доступен $ scope.methodName (). this.methodName()
внутри контроллера означает добавить methos внутри объекта контроллера. $scope.functionName()
находится в HTML и внутри
$scope.functionName(){
this.name="Name";
//or
$scope.myname="myname"//are same}
Вставьте этот код в свой редактор и откройте консоль, чтобы увидеть ...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>this $sope vs controller</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.7/angular.min.js"></script>
<script>
var app=angular.module("myApp",[]);
app.controller("ctrlExample",function($scope){
console.log("ctrl 'this'",this);
//this(object) of controller different then $scope
$scope.firstName="Andy";
$scope.lastName="Bot";
this.nickName="ABot";
this.controllerMethod=function(){
console.log("controllerMethod ",this);
}
$scope.show=function(){
console.log("$scope 'this",this);
//this of $scope
$scope.message="Welcome User";
}
});
</script>
</head>
<body ng-app="myApp" >
<div ng-controller="ctrlExample">
Comming From $SCOPE :{{firstName}}
<br><br>
Comming from $SCOPE:{{lastName}}
<br><br>
Should Come From Controller:{{nickName}}
<p>
Blank nickName is because nickName is attached to
'this' of controller.
</p>
<br><br>
<button ng-click="controllerMethod()">Controller Method</button>
<br><br>
<button ng-click="show()">Show</button>
<p>{{message}}</p>
</div>
</body>
</html>
Я просто прочитал довольно интересное объяснение различий между ними и растущее предпочтение прикреплять модели к контроллеру и псевдоним контроллера для привязки моделей к представлению. http://toddmotto.com/digging-into-angulars-controller-as-syntax/ - статья. Он не упоминает об этом, но при определении директив, если вам нужно поделиться чем-то между несколькими директивами и не хотеть службы (есть законные случаи, когда услуги - это хлопот), тогда прикрепите данные к контроллеру родительской директивы. Служба $ scope предоставляет множество полезных вещей, $ watch является наиболее очевидным, но если все, что вам нужно, привязать данные к представлению, используя простой контроллер и «контроллер как» в шаблоне, отлично и, возможно, предпочтительнее.
Предыдущие версии Angular (pre 1.0 RC) позволили вам использовать это взаимозаменяемо с методом $ scope, но это уже не так. Внутри методов, определенных в области действия this и $ scope, взаимозаменяемы (угловое задает это значение в $ scope), но не внутри внутри вашего конструктора контроллера.
blockquote>Чтобы вернуть это поведение (кто-нибудь знает почему это было изменено?) вы можете добавить:
return angular.extend($scope, this);
в конце вашей функции контроллера (при условии, что $ scope был введен в эту функцию контроллера).
У этого есть хороший эффект наличия доступа к родительской области через объект контроллера, который вы можете получить в дочернем с
require: '^myParentDirective'
Я рекомендую вам прочитать следующее сообщение: http://codetunnel.io/angularjs-controller-as-or-scope/
он очень хорошо описывает преимущества использования «Controller as» для отображения переменных над «$ scope».
Я знаю, что вы конкретно задавали вопросы о методах, а не переменных, но я думаю, что лучше придерживаться одного метода и быть в соответствии с ним.
Итак, по моему мнению, из-за проблемы с переменными, обсуждаемой в сообщении, лучше просто использовать технику «Контроллер как», а также применить ее к методам.
Причиной «addPane» назначается это из-за директивы <pane>
.
Директива pane
делает require: '^tabs'
, которая помещает объект контроллера таблеток из родительской директивы в функция ссылки.
addPane
присваивается this
, так что функция ссылки pane
может ее видеть. Затем в функции pane
link addPane
является просто свойством контроллера tabs
, и это всего лишь tabsControllerObject.addPane. Таким образом, функция связывания указателей панели может получить доступ к объекту контроллера таблеток и, следовательно, получить доступ к методу addPane.
Надеюсь, что мои объяснения достаточно ясны. Это трудно объяснить.
В этом курсе ( https://www.codeschool.com/courses/shaping-up-with-angular-js ) они объясняют, как использовать «это» и многие другие вещи.
Если вы добавите метод к контроллеру через этот метод, вы должны вызвать его в представлении с именем контроллера «точка» вашего свойства или метода.
Например, используя ваш контроллер в представлении вы можете иметь такой код:
<div data-ng-controller="YourController as aliasOfYourController">
Your first pane is {{aliasOfYourController.panes[0]}}
</div>
$scope
, поэтому спасибо, что упомянул об этом.
– Matt Montag
11 December 2014 в 04:24
as
и this
, и как это может помочь объяснить разницу?
– dumbledad
11 December 2014 в 15:52
$scope
никогда не упоминался, я научился использовать только this
в контроллерах. Проблема в том, что когда вы начинаете обрабатывать обещания в своем контроллере, у вас есть много проблем с ссылками на this
, и вам нужно начать делать такие вещи, как var me = this
, чтобы ссылаться на модель в this
из функции возврата обещания , Поэтому из-за этого я все еще очень смущен тем, какой метод мне следует использовать, $scope
или this
.
– Bruno Finger
11 March 2015 в 12:12
var me = this
или .bind(this)
всякий раз, когда вы выполняете обещания, или другие вещи, связанные с закрытием. Это не имеет никакого отношения к Угловому.
– Dzmitry Lazerka
18 March 2016 в 06:28
$scope
. Это делает сложную логику гораздо более многоразовой.
– Bruno Finger
21 March 2016 в 10:48