'这'VS $范围,AngularJS控制器 [英] 'this' vs $scope in AngularJS controllers

查看:195
本文介绍了'这'VS $范围,AngularJS控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

创建组件的AngularJS的网页部分,有这样的例子:

 控制器:功能($范围,$元素){
  变种窗格= $ scope.panes = [];
  $ scope.select =功能(窗格){
    angular.forEach(窗格功能(窗格){
      pane.selected = FALSE;
    });
    pane.selected = TRUE;
  }
  this.addPane =功能(窗格){
    如果(panes.length == 0)$ scope.select(面板);
    panes.push(面板);
  }
}

注意方法是如何加入到 $范围,而 addPane 方法被添加到这个。如果我将其更改为 $ scope.addPane 中,code中断。

文档说,其实是有区别的,但它没有提到的区别是什么:


  

previous角的版本(pre 1.0 RC)允许您使用这个互换与 $范围方法,但这已不再是这种情况。内部对范围这个 $范围是可以互换(角套这个定义的方法 $范围),而不是其他控制器的构造函数中。


如何在AngularJS控制器本 $范围工作


解决方案

  

如何这个和$在AngularJS控制器工作范围?


简短的回答


  • 这个

    • 当控制器构造函数被调用,这个是控制器。

    • 当$范围对象上定义的函数被调用时,这个是范围实际上当功能被称为。这可能(或可能不会!)是$范围的功能定义。因此,在函数内部,这个和$范围可能的不可以是相同的。


  • $范围

    • 每个控制器都有一个关联范围$对象。

    • 系统控制器(构造函数)函数负责其关联$范围设置模型的属性和功能/行为。

    • 只有这个范围$对象上定义的方法(和父范围的对象,如果原型继承中播放)来自HTML /视图访问。例如,从NG-点击,过滤器等。


龙答案

一个控制器的功能是一个JavaScript构造函数。当构造函数执行(例如,当一个视图负载),这个(即功能语境)设置为控制器对象。因此,在标签的控制器构造函数,当创建addPane功能

  this.addPane =功能(面板){...}

这是控制器对象上创建的,而不是在$范围。意见不能看到addPane功能 - 他们只能访问在$范围定义的功能。换句话说,在HTML,这是不行的:<一个NG点击=addPane(newPane)>将不起作用< / A>

标签的控制器构造函数执行后,我们有以下几点:

该黑色虚线表示原型继承 - 一个分离的范围中典型的范围继承。 (它不中典型从那里该指令在HTML遇到有效范围继承。)

现在,该窗格指导的链接功能想和标签指令(这实际上意味着,它需要影响的选项卡隔离$范围以某种方式)进行通信。活动可以被使用,但另一种机制是有窗格指令要求选项卡控制器。 (似乎有成为窗格指令没有机制来要求标签$范围。)

所以,这引出了一个问题:如果我们只访问选项卡控制器,我们怎么进入隔离卡$范围(这是我们真正想要的)

好了,红色虚线就是答案。该addPane()函数的范围(我指的是JavaScript的功能范围内/关闭这里)给出的标签功能访问隔离$范围。即addPane()有上图​​中因为addPane()的定义时创建一个封闭的访问选项卡IsolateScope。 (如果我们代替标签$范围对象上定义addPane(),窗格指令将无法获得这个功能,并且因此就没有办法与标签$范围进行通信。)

要回答你的问题的另一部分:如何做的控制器$工作范围

在上$范围定义的函数,这个设置为有效的地方/函数被调用时,$范围。假设我们有以下的HTML:

 < D​​IV NG控制器=ParentCtrl>
   <一个NG点击=logThisAndScope()>日志本和$范围< / A> - 父范围
   < D​​IV NG控制器=ChildCtrl>
      <一个NG点击=logThisAndScope()>日志本和$范围< / A> - 子作用域
   < / DIV>
< / DIV>

以及 ParentCtrl (独资)有

  $ scope.logThisAndScope =功能(){
    的console.log(这一点,$范围)
}

单击第一个链接将显示这个 $范围都是一样的,因为的范围实际上当函数被调用的是关联的范围 ParentCtrl

单击第二个链接将显示这个 $范围不会相同,因为有效范围时调用函数的与 ChildCtrl 相关联的范围。所以在这里,这个设置为 ChildCtrl $范围。里面的方法, $范围仍是的 ParentCtrl $范围。

小提琴

我尽量不使用这个在$范围定义,因为它变得扑朔迷离一个函数,$范围受到影响,尤其是考虑到NG-重复内,NG -include,NG-开关和指令都可以创建自己的子作用域。

In the "Create Components" section of AngularJS's homepage, there is this example:

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);
  }
}

Notice how the select method is added to $scope, but the addPane method is added to this. If I change it to $scope.addPane, the code breaks.

The documentation says that there in fact is a difference, but it doesn't mention what the difference is:

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.

How does this and $scope work in AngularJS controllers?

解决方案

"How does 'this' and $scope work in AngularJS controllers?"

Short answer:

  • this
    • When the controller constructor function is called, this is the controller.
    • When a function defined on a $scope object is called, this is the "scope in effect when the function was called". This may (or may not!) be the $scope that the function is defined on. So, inside the function, this and $scope may not be the same.
  • $scope
    • Every controller has an associated $scope object.
    • A controller (constructor) function is responsible for setting model properties and functions/behavior on its associated $scope.
    • Only methods defined on this $scope object (and parent scope objects, if prototypical inheritance is in play) are accessible from the HTML/view. E.g., from ng-click, filters, etc.

Long answer:

A controller function is a JavaScript constructor function. When the constructor function executes (e.g., when a view loads), this (i.e., the "function context") is set to the controller object. So in the "tabs" controller constructor function, when the addPane function is created

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

it is created on the controller object, not on $scope. Views cannot see the addPane function -- they only have access to functions defined on $scope. In other words, in the HTML, this won't work: <a ng-click="addPane(newPane)">won't work</a>.

After the "tabs" controller constructor function executes, we have the following:

The dashed black line indicates prototypal inheritance -- an isolate scope prototypically inherits from Scope. (It does not prototypically inherit from the scope in effect where the directive was encountered in the HTML.)

Now, the pane directive's link function wants to communicate with the tabs directive (which really means it needs to affect the tabs isolate $scope in some way). Events could be used, but another mechanism is to have the pane directive require the tabs controller. (There appears to be no mechanism for the pane directive to require the tabs $scope.)

So, this begs the question: if we only have access to the tabs controller, how do we get access to the tabs isolate $scope (which is what we really want)?

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.

这篇关于'这'VS $范围,AngularJS控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆