this vs $scope

------------------------------------------------------------------------------

'this' vs $scope 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.(当控制器构造函数被“调用”时,this就是控制器函数)
    • 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!)(this可能是也可不能不是$scope) 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(每个控制器都有一个与其相关联的$scope).
    • A controller (constructor) function is responsible for setting model properties and functions/behaviour 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(点击子控制器时,this指向了子控制器(this的指向问题),$scope仍旧指向了父控制器).

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.

--------------------------------------------------------------------------

Angular this vs $scope

最近在Angular项目中遇到关于controller内使用$scope&this 暴露数据的问题,下面来分析一下:

“controller as” 是Angular在1.2版本后新增的语法,我将从引用方式,作用范围,对象对比三个方面做两者的比较:

一、引用方式:

1) $scope 只需要在注入中声明,后面就可以直接在附加数据对象:

controller:

function ACtrl($scope) {

$scope.test = "一个例子"; //在$scope对象中加入test

}

html:

<div ng-controller="ACtrl">

{{test}}

</div>

2) this 则采用了controller as(需要版本为ng 1.2+)写法:

controller:

function BCtrl() {

var vm = this;

this.test = "一个例子"; //在this对象中加入test

}

html:

<!-- vm为自己为当前控制器作的一个简略记号,也可以写作 BCtrl as b,

后面变量便可以在b中引出 如b.test -->

<div ng-controller="BCtrl as vm">

{{vm.test}}

</div>

二、作用范围:

1) $scope 中的变量或数据对象我们可以全部拿到,并且上级控制器中的变量也可以在下级控制器中被获取到:

controller:

function ParentCtrl($scope) {

$scope.test = "测试";

$scope.cover ="覆盖测试";

}

function ChildCtrl($scope) {

$scope.cover ="子覆盖测试";

var test = $scope.test; //“测试”

}

html:

<div ng-controller="ParentCtrl">

<p>Parent-test : {{test}}</p>

<p>Parent-cover : {{cover}}</p>

<div ng-controller="ChildCtrl">

<p>Child-test : {{test}}</p>

<p>Child-cover : {{cover}}</p>

</div>

</div>

我在父控制器ParentCtrl中声明的test变量并未在子控制器ChildCtrl中做声明,而在ChildCtrl作用范围内的Child-test 中,test却输出了”测试”;基于此我再做了一次覆盖测试,检测结果显示,当父子控制器同时存在相同的变量时, 父子控制器各自范围内的值不会被覆盖;

2) this 中的变量则只适用于当前控制器:

controller:

function ParentCtrl($scope) {

var vm = this;

vm.test = "测试";

vm.cover ="覆盖测试";

}

function ChildCtrl($scope) {

var vm = this;

vm.cover ="子覆盖测试";

}

html:

<div ng-controller="ParentCtrl as parent">

<p>Parent-test : {{parent.test}}</p>

<p>Parent-cover : {{parent.cover}}</p>

<div ng-controller="ChildCtrl as child">

<p>Child-test : {{child.test}}</p>

<p>Child-cover : {{child.cover}}</p>

</div>

<div ng-controller="ChildCtrl as parent">

<p>Child-test : {{parent.test}}</p>

<p>Child-cover : {{parent.cover}}</p>

</div>

</div>

在使用this的时候,各层级变量的命名空间是平行的状态,模板html中只可以拿到当前控制器下声明的变量。

三、对象对比:

controller:

function CCtrl($scope) {

var vm = this;

$scope.logThisAndScope = function() {

console.log(vm === $scope)

}

}

vm与$scope实际上是不相等的,在console中我们可以看到

vm: Constructor;

$scope: $get.Scope.$new.Child;

而在$scope中又包含了一个变量vm: Constructor

所以,$scope和this的实际关系,实际结构是

$scope: {

...,

vm: Constructor,

...

}

那么我们可以整理如下:

$scope 当控制器在写法上形成父子级关系时,子级没有的变量或方法父级会自动强加在子级身上,子级可以任意获取到当前父级的变量或方法,该种形式是不可逆的,即父级无法通过$scope获取到子级的任意变量或方法。

this      则像一个独立的个体,所有东西都是由自己管理,也就不存在父子级变量混淆关系了。

那数据共享该如何进行呢?数据业务逻辑我觉得还是交给更专业的service来处理吧。

两种方式其实在性能上并无优劣之分,只有代码习惯的选择。

这或许可以取决于我们观察的角度,其实可以理解为私用跟公用的区别!

$event

$event服务就是对原生事件的封装,但在ng中,$event服务的意义更主要是在parent-child控制器中进行通信。

In cases where the components of our web application are loosely connected, such as when we require user authentication and handle authorization, it’s not always feasible to handle the immediate communication without coupling our components together.
For example, if our back end responds to a request with a status code of 401 (indicative of an unauthorized request), we expect that our web app won’t allow our user to stay connected to the current view. In this case, we’d want our app to redirect the user to a login or signup page.
Given this logic, we cannot tell our controllers to set a new location from the outside. We also want this specific functionality to space across multiple scopes so we can protect multiple scopes using the same behavior. We need another way to communicate between them.
Angular’s scopes are hierarchical in nature: They can naturally communicate back and forth through parent-child relationships. Oftentimes, however, our scopes don’t share variables, and they often perform completely different functions from each other, regardless of their place in the parent tree.
For these cases, we have the ability to communicate between our scopes by propagating events up and down the chain(通过事件传播在不同的作用域上进行通信)

What are Events

Just as the browser responds to browser-level events, such as a mouse click or a page scroll, our Angular app can respond to Angular events(angualr应用可以响应angualr事件). This fact gives us the advantage of being able to communicate across our application inside nested components(在不同的组件之间) that are not built with other
Note that the Angular event system does not share the browser event system, meaning that, by design, we can only listen for Angular events, not DOM events on scopes.
We can think of events as snippets of information propagated across an application that generally (optionally) contain information about what’s happening inside of that application.

可以把事件当做一段信息,这段信息包含了“发生的事件”,这段信息在angualr应用之间进行传播。

Event Propagation(事件传播)

Since scopes are hierarchical, we can pass events up or down the scope chain.

A generally good rule of thumb for choosing the event passing method that we’ll use is to look at the scope from which we’re firing the event.

If we want to notify the entire event system (thus allowing any scope to handle the event), we’ll want to broadcast downwards.
On the other hand, if we want to alert a global module (so to speak), we’ll end up needing to alert our higher-level scopes ($rootScope, for instance), and we’ll need to pass an event upwards. It’s a good idea to limit the number of notifications sent to the global level, particularly because events, although very powerful, introduce complexity into our apps.
For example, when we’re routing, the ‘global’ app state needs to know at which page the app is currently set, while, on the other hand, if we’re communicating between a tab directive to its child pane directives, we’ll need to send the event downwards

Bubbling an Event Up with $emit(向上传播,child->parent)

To dispatch an event to travel up the scope chain (from child scopes to parent scopes), we’ll use the $emit() function.

Sending an Event Down with $broadcast(向下传播,parent->child )

To pass an event downwards (from parent scopes to child scopes), we use the $broadcast() function

On the $broadcast() method, every single child scope(采用broadcast方法,每个子作用域都会收到) that registers a listener will receive this message. The event propagates to all directives and indirect scopes of the current scope and calls every single listener all the way down. We cannot cancel events sent using the $broadcast() method.

Listening(事件监听) 

To listen for an event, we can use the $on() method. This method registers a listener for the event bearing a particular name. The event name is simply the event type fired in Angular

Angular this vs $scope $event事件系统的更多相关文章

  1. 如何使用OpenCart 2.x Event事件系统

    如何使用OpenCart 2.x Event事件系统 OpenCart 2.x 包含很多新特性,其中之一就是专为开发者提供的事件系统,Event System.它允许你在不修改原有系统代码的基础上( ...

  2. angular中的scope

    angular.element($0).scope() 什么是scope? scope是一个refer to the application model的object.它是一个expression的执 ...

  3. [Angular 2] @Input & @Output Event with ref

    The application is simple, to build a color picker: When click the rect box, it will check the color ...

  4. [Angular] The Select DOM Event and Enabling Text Copy

    When we "Tab" into a input field, we want to select all the content, if we start typing, i ...

  5. angular 指令作用域 scope

    转载自:https://segmentfault.com/a/1190000002773689 下面我们就来详细分析一下指令的作用域. 在这之前希望你对AngularJS的Directive有一定的了 ...

  6. angularjs获取元素以及angular.element()用法

    addClass()-为每个匹配的元素添加指定的样式类名 after()-在匹配元素集合中的每个元素后面插入参数所指定的内容,作为其兄弟节点 append()-在每个匹配元素里面的末尾处插入参数内容 ...

  7. 后端学 Angular 2 —— 组件间通信

    1. 父组件向子组件传递信息 使用@Input 子组件的属性用 @Input 进行修饰,在父组件的模板中绑定变量 例子: import { Component, OnInit, Input } fro ...

  8. Angular实现递归指令 - Tree View

    在层次数据结构展示中,树是一种极其常见的展现方式.比如系统中目录结构.企业组织结构.电子商务产品分类都是常见的树形结构数据. 这里我们采用Angular的方式来实现这类常见的tree view结构. ...

  9. laravel Event执行顺序

    laravel一大特色就是event事件系统.一般首先要listen一个事件,随后fire那个事件,这时执行路径将会调用event handler,返回后继续执行.例如: Event::listen( ...

随机推荐

  1. Spring.Net-DI依赖注入和Ioc控制反转

    Spring.Core作为整个Spring框架的基础,实现了依赖注入的功能.Spring框架的其它模块都要依赖或扩展该模块. IObjectFactory接口,该接口实现了工厂模式,使用它可以帮我们创 ...

  2. 偏执的我从Linux到Windows的感受

    可能很多人知道一个比我还偏执的技术狂人,也就是当年被知乎很多谈论的王垠. 他曾经写过好几篇轰动一时的文章,比如<完全用linux工作>.此文也影响了一批人拥抱Linux.不过不久之后他又写 ...

  3. 使用 Rx 中预定义的 Subject

    看到一幅有趣的关于 Rx 学习的图,想知道学习 Rx 的学习曲线?不,是峭壁! 我们可以直接通过 Rx 的 Observer 来创建 Observable 对象. 但是,使用这种方式往往比较复杂,在特 ...

  4. ETL的经验总结

    ETL的考虑        做数据仓库系统,ETL是关键的一环.说大了,ETL是数据整合解决方案,说小了,就是倒数据的工具.回忆一下工作这么些年来,处理数据迁移.转换的工作倒还真的不少.但是那些工作基 ...

  5. ASP.NET Web API中的Routing(路由)

    [译]Routing in ASP.NET Web API 单击此处查看原文 本文阐述了ASP.NET Web API是如何将HTTP requests路由到controllers的. 如果你对ASP ...

  6. UITabelview的删除

    删除的效果 Automatic Bottom Fade left middle none right top 简单删除 先删除数据源里的数据,然后再删除cell,否者会报错 let indexPath ...

  7. PHP绿色集成环境在云服务器上的应用,PHPWAMP在服务器上搭建网站案例

    问:什么叫WAMP?答:Windows下的Apache+Mysql+PHP,称之为WAMP. 本文案例采用的PHP集成环境是我自己开发的纯绿色版WAMP软件(PHPWAMP). 我在这款集成环境里集成 ...

  8. webStorm支持.wxml文件高亮显示

    微信小程序官方说明需要在微信开发者工具中开发运行,但这个工具着实不咋地. 我是使用webstrom编辑,然后在微信开发者工具中热加载查看效果,因为webstrom默认并不支持*.wxml,添加使用xm ...

  9. 【51Nod】1005 大数加法

    给出2个大整数A,B,计算A+B的结果. Input 第1行:大数A 第2行:大数B (A,B的长度 <= 10000 需注意:A B有可能为负数) Output 输出A + B Input示例 ...

  10. D3.js:交互式操作

    用户用于交互的工具一般有三种:鼠标.键盘.触屏. 1. 添加交互 对某一元素添加交互操作十分简单,代码如下: //画布大小 var width = 500, height = 500; // 在bod ...