Основное использование области [дубликат]

Перейдите к Manage Jenkins / Global Tool Configuration и установите Path to Git executable:

966
задан Peter Mortensen 22 October 2015 в 17:13
поделиться

7 ответов

«Как this и $scope работают в контроллерах AngularJS?»

Короткий ответ:

  • this Когда вызывается функция конструктора контроллера, this - контроллер. Когда вызывается функция, определенная на объекте $scope, this является «областью действия, когда функция была вызвана». Это может (или не может быть!) Быть $scope, что функция определена. Таким образом, внутри функции this и $scope могут быть не одинаковыми.
  • $scope Каждый контроллер имеет ассоциированный объект $scope. Функция контроллера (конструктора) отвечает за настройку свойств модели и функций / поведения на ее ассоциированном $scope. Только методы, определенные на этом объекте $scope (и родительские объекты области, если прототипическое наследование находится в игре) доступны из HTML / view. Например, из ng-click, фильтров и т. Д.

Длинный ответ:

Функция контроллера - это функция JavaScript-конструктора. Когда функция конструктора выполняется (например, при загрузке представления), this (то есть «контекст функции») устанавливается в объект контроллера. Таким образом, в функции конструктора контроллера «tabs», когда создается функция addPane

this.addPane = function(pane) { ... }

, она создается на объекте контроллера, а не на $ scope. Представления не видят функцию addPane - они имеют доступ только к функциям, определенным в области $ scope. Другими словами, в HTML это не сработает:

<a ng-click="addPane(newPane)">won't work</a>

После выполнения функции конструктора контроллера «tabs» мы имеем следующее:

after tabs controller constructor function [/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.

Fiddle

Я пытаюсь не использовать this внутри функция, определенная в области $ scope, так как она запутывает, на какой объект влияет область видимости, особенно учитывая, что ng-repeat, ng-include, ng-switch и директивы могут создавать собственные дочерние области.

950
ответ дан Andrew Tobilko 18 August 2018 в 17:21
поделиться
  • 1
    @tamakisquare, я считаю, что выделенный вам полужирный текст относится к тому, когда вызывается функция конструктора контроллера, т. е. когда создается контроллер = связанный с $ scope. Это не применяется позже, когда произвольный код JavaScript вызывает метод, определенный в объекте $ scope. – Mark Rajcok 19 February 2013 в 22:04
  • 2
    Обратите внимание, что теперь можно вызвать функцию addPane () непосредственно в шаблоне, назвав контроллер: «MyController as myctrl»; а затем myctrl.addPane (). См. docs.angularjs.org/guide/concepts#controller – Christophe Augier 29 November 2013 в 23:44
  • 3
    Слишком сложная сложность. – Inanc Gumus 7 June 2014 в 09:33
  • 4
    Это очень информативный ответ, но когда я вернулся с практической проблемой (, как вызывать $ scope. $ Apply () в методе контроллера, определяемом с помощью 'this' ), я не смог его обработать , Поэтому, хотя это еще полезный ответ, я нахожу «присущую сложность». озадачивает. – dumbledad 15 December 2014 в 19:10
  • 5
    Javascript - много веревки [повесить себя]. – AlikElzin-kilaka 1 June 2015 в 07:09

$ 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>
0
ответ дан Aniket Jha 18 August 2018 в 17:21
поделиться

Я просто прочитал довольно интересное объяснение различий между ними и растущее предпочтение прикреплять модели к контроллеру и псевдоним контроллера для привязки моделей к представлению. http://toddmotto.com/digging-into-angulars-controller-as-syntax/ - статья. Он не упоминает об этом, но при определении директив, если вам нужно поделиться чем-то между несколькими директивами и не хотеть службы (есть законные случаи, когда услуги - это хлопот), тогда прикрепите данные к контроллеру родительской директивы. Служба $ scope предоставляет множество полезных вещей, $ watch является наиболее очевидным, но если все, что вам нужно, привязать данные к представлению, используя простой контроллер и «контроллер как» в шаблоне, отлично и, возможно, предпочтительнее.

26
ответ дан Derek 18 August 2018 в 17:21
поделиться

Предыдущие версии Angular (pre 1.0 RC) позволили вам использовать это взаимозаменяемо с методом $ scope, но это уже не так. Внутри методов, определенных в области действия this и $ scope, взаимозаменяемы (угловое задает это значение в $ scope), но не внутри внутри вашего конструктора контроллера.

Чтобы вернуть это поведение (кто-нибудь знает почему это было изменено?) вы можете добавить:

return angular.extend($scope, this);

в конце вашей функции контроллера (при условии, что $ scope был введен в эту функцию контроллера).

У этого есть хороший эффект наличия доступа к родительской области через объект контроллера, который вы можете получить в дочернем с require: '^myParentDirective'

3
ответ дан Kamil Szot 18 August 2018 в 17:21
поделиться

Я рекомендую вам прочитать следующее сообщение: http://codetunnel.io/angularjs-controller-as-or-scope/

он очень хорошо описывает преимущества использования «Controller as» для отображения переменных над «$ scope».

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

Итак, по моему мнению, из-за проблемы с переменными, обсуждаемой в сообщении, лучше просто использовать технику «Контроллер как», а также применить ее к методам.

15
ответ дан Liran Brimer 18 August 2018 в 17:21
поделиться

Причиной «addPane» назначается это из-за директивы <pane>.

Директива pane делает require: '^tabs', которая помещает объект контроллера таблеток из родительской директивы в функция ссылки.

addPane присваивается this, так что функция ссылки pane может ее видеть. Затем в функции pane link addPane является просто свойством контроллера tabs, и это всего лишь tabsControllerObject.addPane. Таким образом, функция связывания указателей панели может получить доступ к объекту контроллера таблеток и, следовательно, получить доступ к методу addPane.

Надеюсь, что мои объяснения достаточно ясны. Это трудно объяснить.

50
ответ дан Mon Calamari 18 August 2018 в 17:21
поделиться
  • 1
    Спасибо за объяснение. Документы показывают, что контроллер - это просто функция, которая устанавливает область действия. Почему контроллер обрабатывается как объект, если все действие происходит в области? Почему бы просто не передать родительскую область в функцию связывания? Изменить. Чтобы лучше сформулировать этот вопрос, если методы контроллера и методы области действия работают в одной и той же структуре данных (область действия), почему бы не поместить их все в одном месте? – Alexei Boronine 24 July 2012 в 01:23
  • 2
    По-видимому, родительская область не передается в функцию lnk из-за желания поддерживать «повторно используемые компоненты», которые не должны случайно считывать или изменять данные в родительской области. & Quot; Но если директива действительно хочет / нуждается в чтении или изменении НЕКОТОРЫХ СПЕЦИФИЧЕСКИХ данных в родительской области (например, в директиве 'pane'), это требует некоторых усилий: «потребовать» контроллер, где находится желаемая родительская область, затем определить метод на этом контроллере (используйте 'this' not $ scope) для доступа к конкретным данным. Поскольку желаемая родительская область не вводится в функцию lnk, я полагаю, что это единственный способ сделать это. – Mark Rajcok 13 September 2012 в 04:42
  • 3
    – Andrew Joslin 13 September 2012 в 14:28
  • 4
    – Mark Rajcok 1 January 2013 в 18:56

В этом курсе ( 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>
15
ответ дан Sandro 18 August 2018 в 17:21
поделиться
  • 1
    Пройдя курс, меня сразу же смутил код, используя $scope, поэтому спасибо, что упомянул об этом. – Matt Montag 11 December 2014 в 04:24
  • 2
    В этом курсе вообще не упоминается $ scope, они просто используют as и this, и как это может помочь объяснить разницу? – dumbledad 11 December 2014 в 15:52
  • 3
    Мой первый контакт с Angular был из упомянутого курса, и поскольку $scope никогда не упоминался, я научился использовать только this в контроллерах. Проблема в том, что когда вы начинаете обрабатывать обещания в своем контроллере, у вас есть много проблем с ссылками на this, и вам нужно начать делать такие вещи, как var me = this, чтобы ссылаться на модель в this из функции возврата обещания , Поэтому из-за этого я все еще очень смущен тем, какой метод мне следует использовать, $scope или this. – Bruno Finger 11 March 2015 в 12:12
  • 4
    @BrunoFinger К сожалению, вам понадобятся var me = this или .bind(this) всякий раз, когда вы выполняете обещания, или другие вещи, связанные с закрытием. Это не имеет никакого отношения к Угловому. – Dzmitry Lazerka 18 March 2016 в 06:28
  • 5
    @DzmitryLazerka Ты абсолютно прав, но если мы достаточно осторожны, мы можем избежать написания такого уродливого кода. На самом деле, повторно прочитав мой комментарий сегодня, я даже смущен, чтобы сказать что-то, как ручные обещания в контроллере. Такая логика принадлежит где-то еще в приложении. Я тяготею к тому, чтобы иметь их в другом слое сервиса, взаимодействующем с $scope. Это делает сложную логику гораздо более многоразовой. – Bruno Finger 21 March 2016 в 10:48
Другие вопросы по тегам:

Похожие вопросы: