Nice programing

AngularJS 컨트롤러의 'this'vs $ scope

nicepro 2020. 9. 27. 13:57
반응형

AngularJS 컨트롤러의 'this'vs $ scope


AngularJS 홈페이지"Create Components"섹션에 다음 예제가 있습니다.

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$scopeAngularJS와 컨트롤러에서 사용할 수 있습니까?


"어떻게 this$scopeAngularJS와 컨트롤러에서 사용할 수 있습니까?"

짧은 대답 :

  • this
    • 컨트롤러 생성자 함수가 호출되면 this컨트롤러입니다.
    • $scope객체 에 정의 된 this함수가 호출되면 "함수가 호출되었을 때 적용되는 범위"입니다. 이것은 $scope함수가 정의 된 것일 수도 있고 아닐 수도 있습니다 . 따라서, 함수 내에서, this그리고 $scope없는 동일합니다.
  • $scope
    • 모든 컨트롤러에는 관련 $scope개체가 있습니다.
    • 컨트롤러 (생성자) 함수는 연결된 .NET Framework에서 모델 속성 및 함수 / 동작을 설정하는 역할을합니다 $scope.
    • $scope개체 (및 프로토 타입 상속이 실행중인 경우 부모 범위 개체) 에 정의 된 메서드 만 HTML /보기에서 액세스 할 수 있습니다. 예 : from 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에서 지시문이 발생한 유효 범위에서 프로토 타입 적으로 상속되지 않습니다.)

이제 pane 지시문의 링크 함수는 tabs 지시문과 통신하려고합니다 (실제로는 탭에 영향을 미쳐 $ scope를 어떤 식 으로든 분리해야 함). 이벤트를 사용할 수 있지만 또 다른 메커니즘은 pane require이 탭 컨트롤러를 지시 하는 것입니다. ( require$ scope 탭 에 대한 pane 지시문에 대한 메커니즘이없는 것으로 보입니다 .)

그래서 이것은 질문을합니다. 만약 우리가 탭 컨트롤러에 접근 할 수만 있다면, 우리가 $ scope를 분리하는 탭에 어떻게 접근 할 수 있습니까 (우리가 정말로 원하는 것입니다)?

Well, the red dotted line is the answer. The addPane() function's "scope" (I'm referring to JavaScript's function scope/closures here) gives the function access to the tabs isolate $scope. I.e., addPane() has access to the "tabs IsolateScope" in the diagram above because of a closure that was created when addPane() was defined. (If we instead defined addPane() on the tabs $scope object, the pane directive would not have access to this function, and hence it would have no way to communicate with the tabs $scope.)

To answer the other part of your question: how does $scope work in controllers?:

Within functions defined on $scope, this is set to "the $scope in effect where/when the function was called". Suppose we have the following 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>

And the ParentCtrl (Solely) has

$scope.logThisAndScope = function() {
    console.log(this, $scope)
}

Clicking the first link will show that this and $scope are the same, since "the scope in effect when the function was called" is the scope associated with the ParentCtrl.

Clicking the second link will reveal this and $scope are not the same, since "the scope in effect when the function was called" is the scope associated with the ChildCtrl. So here, this is set to ChildCtrl's $scope. Inside the method, $scope is still the ParentCtrl's $scope.

Fiddle

I try to not use this inside of a function defined on $scope, as it becomes confusing which $scope is being affected, especially considering that ng-repeat, ng-include, ng-switch, and directives can all create their own child scopes.


The reason 'addPane' is assigned to this is because of the <pane> directive.

The pane directive does require: '^tabs', which puts the tabs controller object from a parent directive, into the link function.

addPane is assigned to this so that the pane link function can see it. Then in the pane link function, addPane is just a property of the tabs controller, and it's just tabsControllerObject.addPane. So the pane directive's linking function can access the tabs controller object and therefore access the addPane method.

I hope my explanation is clear enough.. it's kind of hard to explain.


I just read a pretty interesting explanation on the difference between the two, and a growing preference to attach models to the controller and alias the controller to bind models to the view. http://toddmotto.com/digging-into-angulars-controller-as-syntax/ is the article. He doesn't mention it but when defining directives, if you need to share something between multiple directives and don't want a service (there are legitimate cases where services are a hassle) then attach the data to the parent directive's controller. The $scope service provides plenty of useful things, $watch being the most obvious, but if all you need to to bind data to the view, using the plain controller and 'controller as' in the template is fine, and arguably preferable.


I recommend you to read the following post: AngularJS: "Controller as" or "$scope"?

It describes very well the advantages of using "Controller as" to expose variables over "$scope".

I know you asked specifically about methods and not variables, but I think that it's better to stick to one technique and be consistent with it.

So for my opinion, because of the variables issue discussed in the post, it's better to just use the "Controller as" technique and also apply it to the methods.


In this course(https://www.codeschool.com/courses/shaping-up-with-angular-js) they explain how to use "this" and many other stuff.

If you add method to the controller through "this" method, you have to call it in the view with controller's name "dot" your property or method.

For example using your controller in the view you may have code like this:

    <div data-ng-controller="YourController as aliasOfYourController">

       Your first pane is {{aliasOfYourController.panes[0]}}

    </div>

Previous versions of Angular (pre 1.0 RC) allowed you to use this interchangeably with the $scope method, but this is no longer the case. Inside of methods defined on the scope this and $scope are interchangeable (angular sets this to $scope), but not otherwise inside your controller constructor.

To bring back this behaviour (does anyone know why was it changed?) you can add:

return angular.extend($scope, this);

at the end of your controller function (provided that $scope was injected to this controller function).

This has a nice effect of having access to parent scope via controller object that you can get in child with require: '^myParentDirective'


$ scope는 'this'와 컨트롤러 'this'가 다르기 때문에 console.log (this)를 컨트롤러 안에 넣으면 object (controller)를 제공하고 this.addPane ()은 컨트롤러 Object에 addPane 메서드를 추가합니다. 그러나 $ scope는 다른 범위를 가지며 해당 범위의 모든 메서드는 $ scope.methodName ()에 의해 액세스되어야합니다. this.methodName()내부 컨트롤러는 컨트롤러 개체 내부에 메 토스를 추가하는 것을 의미합니다. $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>

참고 URL : https://stackoverflow.com/questions/11605917/this-vs-scope-in-angularjs-controllers

반응형