深深钻探AngularJS框架中Scope对象的最好教程,转深切精通

2013年8月2日, 严清 译

译文:掌握AngularJS的功效域Scope

原文:Understanding Scopes

2013年8月2日,
严清 译
译文:了解AngularJS的效用域Scope
原文:Understanding
Scopes

作品转发英文:what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs

浓厚斟酌AngularJS框架中Scope对象的最好教程,angularjsscope

一、遭受的难题 主题素材发出在利用 AngularJS 嵌套 Controller 的时候。因为各类 Controller
都有它对应的 Scope(也正是作用域、调节范围),所以 Controller
的嵌套,也就代表 Scope 的嵌套。那个时候要是多少个 Scope 内都有同名的
Model 会产生如何吗?从子 Scope 如何翻新父 Scope 里的 Model 呢?

那个主题素材很优秀,比如说当前页面是贰个出品列表,那么就需求定义一个ProductListController

function ProductListController($scope, $http) {
  $http.get('/api/products.json')
    .success(function(data){
      $scope.productList = data;
    });
  $scope.selectedProduct = {};
}

您大概看看了在 Scope 里还定义了一个 selectedProduct 的
Model,表示当选了某三个产品。那时会赢得该产品实际情况,而页面通过 AngularJS
中的 $routeProvider 自动更新,拉取新的详细情况页模板,模板中有一个ProductDetailController

function ProductDetailController($scope, $http, $routeParams) {
  $http.get('/api/products/'+$routeParams.productId+'.json')
    .success(function(data){
      $scope.selectedProduct = data;
    });
}

幽默的政工作时间有产生了,在这边也是有四个 selectedProduct ,它会怎么样影响
ProductListController 中的 selectedProduct 呢?

答案是尚未影响。在 AnuglarJS 里子 Scope 确实会一而再父 Scope
中的对象,但当您试下对基本数据类型(string, number, boolean)的
双向数据绑定 时,就能够意识有的意料之外的行为,承袭并不像您想像的那么行事。子
Scope 的属性隐藏(覆盖)了父 Scope 中的同名属性,对子 Scope
属性(表单成分)的改变并不创新父 Scope 属性的值。这些行为其实不是
AngularJS 特有的,JavaScript
本人的原型链正是如此专门的工作的。开荒者平常都未有意识到 ng-repeat, ng-switch,
ng-view 和 ng-include 统统都创设了她们新的子 scopes,所以在用到这么些directive 时也每每出标题。

二、消除的章程 缓和的方法正是不利用基本数据类型,而在 Model 里永久多加二个点.

使用

<input type="text" ng-model="someObj.prop1">

来替代

<input type="text" ng-model="prop1">

是不是很坑爹?上边那个例子很分明地表达了自身所想表明的奇葩现象

app.controller('ParentController',function($scope){
  $scope.parentPrimitive = "some primitive"
  $scope.parentObj = {};
  $scope.parentObj.parentProperty = "some value";
});
app.controller('ChildController',function($scope){
  $scope.parentPrimitive = "this will NOT modify the parent"
  $scope.parentObj.parentProperty = "this WILL modify the parent";
});

查阅 在线演示 DEMO
可是本人真的真的特别很拾贰分需求采用 string number 等原本数据类型如何是好吧?2
个法子——

在子 Scope 中央银行使 $parent.parentPrimitive。 那将阻碍子 Scope
创立它和谐的属性。
在父 Scope 中定义一个函数,让子 Scope
调用,传递原始数据类型的参数给阿爸,从而革新父 Scope
中的属性。(并不总是低价)
三、JavaScript 的原型链承接 调侃达成,我们来深入摸底一下 JavaScript
的原型链。那很主要,特别是当你从服务器端开拓转到前端,你应当会很熟练卓绝的
Class 类承袭,我们来回看一下。

要是父类 parentScope 有如下成员属性 aString, aNumber, anArray, anObject,
以及 aFunction。子类 childScope 原型承袭父类 parentScope,于是大家有:

美高梅开户网址 1

只要子 Scope 尝试去拜谒 parentScope 中定义的属性,JavaScript 会先在子
Scope 中查究,假使没有该属性,则找它一连的 scope
去获得属性,假如持续的原型对象 parentScope
中都从不应该属性,那么继续在它的原型中找找,从原型链一贯往上直到到达rootScope。所以,上面包车型大巴表明式结果都以 ture:

childScope.aString === 'parent string'
childScope.anArray[1] === 20
childScope.anObject.property1 === 'parent prop1'
childScope.aFunction() === 'parent output'

若果大家实施上边包车型客车口舌

childScope.aString = 'child string'

原型链并未被询问,反而是在 childScope 中追加了二个新属性
aString。这么些新属性隐藏(覆盖)了 parentScope
中的同名属性。在底下大家批评 ng-repeat 和 ng-include
时这些定义很入眼。

美高梅开户网址 2

一经大家实践那些操作:

childScope.anArray[1] = '22'
childScope.anObject.property1 = 'child prop1'

原型链被询问了,因为对象 anArray 和 anObject 在 childScope
中从未找到。它们在 parentScope 中被找到了,并且值被更新。childScope
中平素不扩大新的性质,也远非别的新的靶子被创制。(注:在 JavaScript
中,array 和 function 都是指标)

美高梅开户网址 3

要是大家试行那个操作:

childScope.anArray = [100, 555]
childScope.anObject = { name: 'Mark', country: 'USA' }

原型链未有被询问,并且子 Scope
新参预了七个新的指标属性,它们隐藏(覆盖)了 parentScope
中的同名对象属性。

美高梅开户网址 4

相应可以计算

只要读取 childScope.propertyX,并且 childScope 有品质propertyX,那么原型链未有被询问。
借使设置 childScope.propertyX,原型链不会被询问。
终极一种情景,

delete childScope.anArray
childScope.anArray[1] === 22 // true

大家从 childScope
删除了品质,则当大家再次访问该属性时,原型链会被询问。删除对象的属性会让来自原型链中的质量显示出来。

美高梅开户网址 5

四、AngularJS 的 Scope 继承 创造新的 Scope,并且原型承接:ng-repeat, ng-include, ng-switch,
ng-view, ng-controller, directive with scope: true, directive with
transclude: true
制造新的 Scope,但不继续:directive with scope: { …
}。它会创设贰个单身 Scope。
注:暗许情形下 directive 不创制新 Scope,即默许参数是 scope: false。

ng-include

若是在我们的 controller 中,

$scope.myPrimitive = 50;
$scope.myObject  = {aNumber: 11};

HTML 为:

<script type="text/ng-template" id="/tpl1.html">
  <input ng-model="myPrimitive">
</script>
<div ng-include src="'/tpl1.html'"></div>

<script type="text/ng-template" id="/tpl2.html">
  <input ng-model="myObject.aNumber">
</script>
<div ng-include src="'/tpl2.html'"></div>

每三个 ng-include 会生成二个子 Scope,每种子 Scope 都承袭父 Scope。

美高梅开户网址 6

输入(举个例子”77″)到第多个 input 文本框,则子 Scope 将获取一个新的
myPrimitive 属性,覆盖掉父 Scope 的同名属性。那说不定和你预想的不相同样。

美高梅开户网址 7

输入(比方”99″)到第贰个 input 文本框,并不会在子 Scope
成立新的质量,因为 tpl2.html 将 model 绑定到了多少个对象属性(an object
property),原型承袭在那时候发挥了效益,ngModel 寻觅目的 myObject
并且在它的父 Scope 中找到了。

美高梅开户网址 8

比如大家不想把 model 从 number 基础项目改为目的,大家能够用 $parent
改写第贰个模板:

<input ng-model="$parent.myPrimitive">

输入(譬喻”22″)到这么些文本框也不会创制新天性了。model 被绑定到了父 scope
的习性上(因为 $parent 是子 Scope 指向它的父 Scope 的壹脾质量)。

美高梅开户网址 9

对于具有的 scope (原型承继的照旧非承继的),Angular 总是会通过 Scope 的
$parent, $$childHead 和 $$childTail
属性记录父-子关系(也便是持续关系),图中为简化而未画出那一个属性。

在尚未表单元素的情事下,另一种方法是在父 Scope
中定义叁个函数来修改基本数据类型。因为有原型承接,子 Scope
确认保障能够调用那几个函数。举例,

// 父 Scope 中
$scope.setMyPrimitive = function(value) {
  $scope.myPrimitive = value;

查看 DEMO

ng-switch
ng-switch 的原型承袭和 ng-include
一样。所以只要你要求对中央项目数据开始展览双向绑定,使用
$parent,恐怕将其改为 object 对象并绑定到目的的品质,制止子 Scope 覆盖父
Scope 的性质。
ng-repeat
ng-repeat 有少数不平等。假若在大家的 controller 里:

$scope.myArrayOfPrimitives = [ 11, 22 ];
$scope.myArrayOfObjects  = [{num: 101}, {num: 202}]

还有 HTML:

<ul>
  <li ng-repeat="num in myArrayOfPrimitives">
    <input ng-model="num">
  </li>
<ul>
<ul>
  <li ng-repeat="obj in myArrayOfObjects">
    <input ng-model="obj.num">
  </li>
<ul>

对此每贰个 Item,ng-repeat 成立新的 Scope,每贰个 Scope 都持续父
Scope,但同一时间 item 的值也被赋给了新 Scope
的新属性(新属性的名称为循环的变量名)。Angular ng-repeat
的源码实际上是如此的:

childScope = scope.$new(); // 子 scope 原型继承父 scope ...   
childScope[valueIdent] = value; // 创建新的 childScope 属性

要是 item 是三个基础数据类型(就像myArrayOfPrimitives),本质上它的值被复制了一份赋给了新的子 scope
属性。退换那一个子 scope 属性值(比方用 ng-model,即 num)不会转移父 scope
引用的 array。所以地方首个 ng-repeat 里每二个子 scope 获得的 num
属性独立于 myArrayOfPrimitives 数组:

美高梅开户网址 10

这么的 ng-repeat 和您预想中的不等同。在 Angular 1.0.2
及更早的本子,向文本框中输入会变动黄色格子的值,它们只在子 Scope
中可知。Angular 1.0.3+ 今后,输入文本不会再有别的功效了。
我们期望的是输入能更换 myArrayOfPrimitives 数组,而不是子 Scope
里的属性。为此大家亟须将 model 改为一个关于指标的数组(array of
objects)。

据此借使 item
是贰个指标,则对此原对象的贰个引用(而非拷贝)被赋给了新的子 Scope
属性。改造子 Scope 属性的值(使用 ng-model,即 obj.num)也就改换了父
Scope 所引述的目的。所以地点第三个 ng-repeat 可代表为:

美高梅开户网址 11

那才是我们想要的。输入到文本框即会变动深青莲格子的值,该值在父 Scope 和子
Scope 均可知。
ng-controller
利用 ng-controller 举办嵌套,结果和 ng-include 和 ng-switch
一样是健康的原型承继。所以做法也一样不再赘述。然则“三个 controller 使用
$scope 传承来共享新闻被感到是不佳的做法”
应该使用 service 在 controller 间共享数据。

若果你真正要透过持续来共享数据,那么也没怎么非常要做的,子 Scope
能够平素访问具备父 Scope 的性质。
directives
以此要分情形来研商。

暗中同意 scope: false – directive 不会成立新的
Scope,所以并未有原型承继。那看起来很简短,但也很凶险,因为您会感觉directive 在 Scope
中开创了贰个新的习性,而实在它只是利用了三个已存在的属性。那对编写可复用的模块和零部件来讲并不佳。
scope: true – 这时 directive 会创造一个新的子 scope 并接二连三父
scope。借使在同二个 DOM 节点上有多个 directive 都要创制新
scope,则唯有八个新 Scope 会创制。因为有平常的原型承继,所以和
ng-include, ng-switch 同样要注意基础项目数据的双向绑定,子 Scope
属性会覆盖父 Scope 同名属性。
scope: { … } – 那时 directive 创造一个独自的
scope,未有原型承接。这在编写制定可复用的模块和零部件时是相比好的抉择,因为
directive 不会十分大心读写父 scope。不过,偶然候那类 directives
又平常须要拜访父 scope 的性质。对象散列(object hash)被用来创建这几个独立
Scope 与父 Scope 间的双向绑定(使用 ‘=’)或单向绑定(使用
‘@’)。还会有多少个 ‘&’ 用来绑定父 Scope 的表达式。那一个全都从父 Scope
派生创立出地点的 Scope 属性。注意,HTML
属性被用来树立绑定,你无法在对象散列中引用父 Scope
的属性名,你不能够不采纳二个 HTML 属性。举个例子,<div my-directive> 和
scope: { localProp: ‘@parentProp’ } 是无力回天绑定父属性 parentProp 到独门
scope的,你不可能不那样钦点: <div my-directive
the-Parent-Prop=parentProp> 以及 scope: { localProp: ‘@theParentProp’
}。独立的 scope 中 __proto__ 引用了一个 Scope 对象(下图中的桔青莲Object),独立 scope 的 $parent 指向父
scope,所以固然它是独立的还要尚未从父 Scope 原型承袭,它依旧是多个子
scope。

上边包车型地铁图中,大家有 <my-directive interpolated=”{{parentProp1}}”
twowayBinding=”parentProp2″> 和 scope:

{ interpolatedProp: '@interpolated', twowayBindingProp: '=twowayBinding' }。

而且,假诺 directive 在它的 link 函数里做了 scope.someIsolateProp = “I’m
isolated”

美高梅开户网址 12

留神:在 link 函数中运用 attrs.$observe(‘attr_name’, function(value) {
… } 来收获独立 Scope 用 ‘@’ 符号替换的属性值。比方,在 link 函数中有
attrs.$observe(‘interpolated’, function(value) { … } 值将被设为 11.
(scope.interpolatedProp 在 link 函数中是
undefined,相反scope.twowayBindingProp 在 link 函数中定义了,因为用了
‘=’ 符号)
transclude: true – 那时 directive 创立了一个新的 “transcluded” 子
scope,同不时间继续父 scope。所以借使模板片段中的内容(比如那么些就要取代ng-transclude 的内容)要求对父 Scope 的大旨类型数据开始展览双向绑定,使用
$parent,只怕将 model 贰个对象的质量,制止子 Scope 属性覆盖父 Scope
属性。

transcluded 和独立 scope (若是有)是手足关系,每一种 Scope 的 $parent
指向同三个父 Scope。当模板中的 scope 和独门 Scope 同期设有,独立 Scope
属性 $$nextSibling 将会针对模板中的 Scope。
在下图中,假诺 directive 和上个图一律,只是多了 transclude: true

美高梅开户网址 13

翻看 在线 DEMO,例子里有八个 showScope() 函数能够用来检查独立 Scope
和它关系的 transcluded scope。
总结 总共有二种 Scope:

常备实行原型承继的 Scope —— ng-include, ng-switch, ng-controller,
directive with scope: true
一般性原型传承的 Scope 但拷贝赋值 —— ng-repeat。 种种 ng-repeat
的巡回都成立新的子 Scope,并且子 Scope 总是获得新的天性。
单身的 isolate scope —— directive with scope: {…}。它不是原型承袭,但
‘=’, ‘@’ 和 ‘&’ 提供了走访父 Scope 属性的建制。
transcluded scope —— directive with transclude:
true。它也根据原型继承,但它同期是其余 isolate scope 的小伙子。
对于具备的 Scope,Angular 总是会经过 Scope 的 $parent, $$childHead 和
$$childTail 属性记录父-子关系。

PS:scope和rootscope的区别 scope是html和单个controller之间的桥梁,数据绑定就靠她了。rootscope是各种controller中scope的大桥。用rootscope定义的值,能够在各种controller中使用。上边用实例详细的证实一下。
1,js代码

phonecatApp.controller('TestCtrl',['$scope','$rootScope', 
  function($scope,$rootScope) { 
    $rootScope.name = 'this is test'; 
  } 
]); 

phonecatApp.controller('Test111Ctrl',['$scope','$rootScope', 
  function($scope,$rootScope) { 
    $scope.name = $rootScope.name; 
  } 
]); 

2,html代码

<div ng-controller="TestCtrl"> 
  I set the global variable.<strong>{{$root.name}}</strong> 
</div> 

<div ng-controller="Test111Ctrl"> 
  1,get global variable .<strong>{{name}}</strong><br> 
  2,get global variable .<strong>{{$root.name}}</strong> 
</div> 

3,显示结果

I set the global variable.this is test 
1,get global variable .this is test 
2,get global variable .this is test 

由结果能够看出来,$rootScope.name设置的变量,在装有controller里面都以能够直接用{{$root.name}}来呈现的,很有力。那本来也能够赋值给scope.
 

概叙:

AngularJS中,子功用域一般都会透过JavaScript原型承袭机制接轨其父成效域的习性和方式。但有一个例外:在directive中选拔scope:{...},这种措施开创的功效域是四个独立的”Isolate”功能域,它也是有父成效域,但父成效域不在其原型链上,不会对父功用域举办原型承袭。这种情势定义效用域平时用于协会可复用的directive组件。

作用域的原型继承是特别轻巧广泛的,以至你不用关切它的运营。直到你在子功能域中向父作用域的原始类型属性使用双向数据绑定2-way
data
binding
,比如Form表单的ng-model为父效能域中的属性,且为原始类型,输入数据后,它不会如你希望的那样运转——AngularJS不会把输入数据写到你期望的父成效域属性中去,而是径直在子功效域创立同名属性并写入数据。这一个作为符合JavaScript原型承接机制的行为。AngularJS新手平常没有认知到ng-repeat
ng-switchng-viewng-include 都会创设子效用域, 所以平日出标题。
(见 示例)

深深钻探AngularJS框架中Scope对象的最好教程,转深切精通。幸免这些标题标特等实行是在ng-model中总使用.,参见小说 always have a
‘.’ in your ng-models。

比如:

<inputtype="text"ng-model="someObj.prop1">

优于:

<inputtype="text"ng-model="prop1">

一旦你一定要直接接纳原始类型,要小心两点:

  1. 在子功用域中应用
    $parent.parentScopeProperty,这样能够一贯更动父效用域的习性。
  2. 在父作用域中定义函数,子功能域通过原型承接调用函数把值传递给父功效域(这种办法极少使用)。

概叙:

AngularJS中,子效能域一般都会因此JavaScript原型承接机制接轨其父成效域的质量和章程。但有一个分裂:在directive中应用scope:
{ …
},这种方法开创的功能域是三个单独的”Isolate”效能域,它也可能有父功效域,但父成效域不在其原型链上,不会对父成效域进行原型承袭。这种艺术定义作用域平日用于社团可复用的directive组件。功能域的原型承接是特别简单普及的,乃至你不用关切它的运作。直到你在子成效域中向父功能域的原始类型属性使用双向数据绑定2-way
data
binding
,譬喻Form表单的ng-model为父功用域中的属性,且为原始类型,输入数据后,它不会如您指望的那样运转——AngularJS不会把输入数据写到你愿意的父成效域属性中去,而是间接在子功能域创设同名属性并写入数据。那个作为符合JavaScript原型承袭机制的一颦一笑。AngularJS新手常常未有认知到ng-repeat、
ng-switch、ng-view和ng-include 都会创立子作用域, 所以常常出难点。 (见
示例)制止这么些主题素材的一级推行是在ng-model香港中华总商会使用.,参见小说
always have a ‘.’ in your
ng-models。
比如:

<input type="text" ng-model="someObj.prop1">

优于:

<input type="text" ng-model="prop1">

一旦你势须求直接行使原始类型,要小心两点:
在子成效域中运用
$parent.parentScopeProperty,那样能够一向改换父效能域的习性。在父作用域中定义函数,子功效域通过原型承继调用函数把值传递给父功用域(这种艺术极少使用)。

         
 中文:

你也许感兴趣的文章:

  • angularJS 中$scope方法使用指南
  • javascript中的效能域scope介绍

一、境遇的主题材料 难点发生在应用 AngularJS 嵌套 Controller 的时候。因为种种Controlle…

正文:

  • JavaScript Prototypal Inheritance
  • Angular Scope Inheritance
    • ng-include
    • ng-switch
    • ng-view
    • ng-repeat
    • 美高梅开户网址 ,ng-controller
    • directives

正文:

JavaScript Prototypal
Inheritance
Angular Scope
Inheritanceng-include
ng-switch
ng-view
ng-repeat
ng-controller
directives

JavaScript 原型承继机制
您不能够不完全理解JavaScript的原型承继机制,特别是当你有后端开拓背景和类承接经验的时候。所以我们先来回想一下原型承继:
如若父作用域parentScope具备以下属性和格局:aString、aNumber、anArray、anObject、aFunction。子功用域childScope假如从父功用域parentScope实行原型承继,我们将看到:

normal prototypal inheritance

(注:为节约空间,anArray使用了血牙红方块图)
要是大家在子功效域中访问五个父功效域中定义的属性,JavaScript首先在子功能域中找找该属性,没找到再从原型链上的父功用域中检索,要是还没找到会再往上一流原型链的父功能域找寻。在AngularJS中,功能域原型链的最上部是$rootScope,JavaScript寻觅到$rootScope停止。所以,以下表明式均为true:

childScope.aString === 'parent string'childScope.anArray[1] === 20childScope.anObject.property1 === 'parent prop1'childScope.aFunction() === 'parent output'

举个例子我们进行如下操作:

childScope.aString = 'child string'

因为大家赋值目标是子效能域的性质,原型链将不会被询问,贰个新的与父成效域中属性同名的习性aString将被加多到当前的子功能域childScope中。

shadowing

设若大家开始展览如下操作:
childScope.anArray[1] = ’22’childScope.anObject.property1 = ‘child
prop1’

因为大家的赋值指标是子功能域属性anArray和anObject的子属性,也正是说JavaScript必须先要先找找anArray和anObject
那三个目的——它们必须为指标,不然不能写入属性,而那五个对象不在当前子成效域,原型链将被询问,在父成效域中找到那八个对象,
然后对那多少个对象的天性[1]和property1举行赋值操作。子功效域中不会不会创建多个新的同名属性!(注意JavaScript中数组和函数均是目的——引用类型)

follow the chain

假定大家开始展览如下操作:

childScope.anArray = [100, 555]childScope.anObject = { name: 'Mark', country: 'USA' }

一样因为大家赋值指标是子效能域的质量,原型链将不会被询问,,JavaScript会直接在子功效域成立三个同名属性,其值分别为数组和目的。

not following the chain

   一、AngularJS 中的 Scope(scope即成效域、成效范围)所涉及知识点大约预览图

 美高梅开户网址 14

JavaScript 原型承接机制

你不能够不完全知晓JavaScript的原型承接机制,尤其是当你有后端开垦背景和类承袭经验的时候。所以大家先来回看一下原型承继:

举个例子父成效域parentScope持有以下属性和艺术:aStringaNumberanArrayanObjectaFunction。子效用域childScope只要从父成效域parentScope展开原型继承,我们将看到:

美高梅开户网址 15

(注:为节约空间,anArray采纳了米白方块图)

假诺我们在子功效域中做客三个父功效域中定义的天性,JavaScript首先在子作用域中索求该属性,没找到再从原型链上的父成效域中寻觅,假诺还没找到会再往上拔尖原型链的父功能域寻找。在AngularJS中,效率域原型链的上边是$rootScope,JavaScript寻找到$rootScope截止。所以,以下表明式均为true

childScope.aString ==='parent string'  childScope.anArray[1]===20  childScope.anObject.property1 ==='parent prop1'  childScope.aFunction()==='parent output'

假设大家开展如下操作:

childScope.aString ='child string'

因为大家赋值指标是子功效域的性能,原型链将不会被询问,二个新的与父功效域中属性同名的习性aString将被增多到当前的子效率域childScope中。

美高梅开户网址 16

比方我们举行如下操作:

childScope.anArray[1]='22'  childScope.anObject.property1 ='child prop1'

因为大家的赋值指标是子功用域属性anArrayanObject的子属性,相当于说JavaScript必须先要先找找anArrayanObject那多少个指标——它们必须为指标,不然无法写入属性,而这两个对象不在当前子功效域,原型链将被询问,在父成效域中找到那多少个对象,
然后对那八个对象的特性[1]property1进展赋值操作。子作用域中不会不会成立四个新的同名属性!(注意JavaScript中数组和函数均是指标——引用类型)

美高梅开户网址 17

一经大家开始展览如下操作:

childScope.anArray =[100,555]  childScope.anObject ={ name:'Mark', country:'USA'}

无差别于因为我们赋值目的是子功效域的性质,原型链将不会被询问,,JavaScript会直接在子功用域制造四个同名属性,其值分别为数组和目的。

美高梅开户网址 18

要点:

  • 假诺大家读取childScope.propertyX,并且childScope存在propertyX,原型链不会被询问;
  • 假若大家写入childScope.propertyX, 原型链也不会被询问;
  • 一旦大家写入childScope.propertyX.subPropertyY,
    并且childScope不存在propertyX,原型链将被询问——查找propertyX

最后一点:

delete childScope.anArray  childScope.anArray[1]===22// true

设若大家先删除了子成效域childScope的属性,然后再读取该属性,因为找不到该属性,原型链将被询问。

美高梅开户网址 19

要点:

假定大家读取childScope.propertyX,并且childScope存在propertyX,原型链不会被询问;
假设我们写入childScope.propertyX, 原型链也不会被询问;
一经大家写入childScope.propertyX.subPropertyY,
并且childScope不设有propertyX,原型链将被询问——查找propertyX。

   二、AngularJS中决定器间嵌套难题

在选取 AngularJS 嵌套 Controller 的时候。因为种种 Controller
都有它对应的 Scope(相当于作用域、调整范围),所以 Controller
的嵌套,也就代表 Scope 的嵌套。

其有时候借使多个 Scope 内都有同名的 Model
会产生哪些吧?从子 Scope
怎么着翻新父 Scope 里的 Model 呢?

   2.1
老爹和儿子嵌套调控器scope中属性名一样期(准确说基本数据类型属性名)情状

在AngularJS中子scope会承接父scope中的对象,但当你试下对着力数据类型(string, number,
boolean)
的 双向数据绑定 时,子 Scope 的个性隐藏(覆盖)了父 Scope 中的同名属性,对子 Scope 属性(表单成分)的改变并不创新父 Scope 属性的值。

美高梅开户网址 20

在线编辑代码  请点击自身哦 这种行为其实不是 AngularJS
特有的,JavaScript 本人的原型链正是这么专门的学业的。

开荒者日常都并未有发觉到 ng-repeat,
ng-switch, ng-view 和 ng-include 统统都成立了他们新的子 scopes,所以在用到那几个 directive
时也时常出难题。

   2.1 子 Scope 如何翻新父 Scope 里的
Model 呢?

 解决方案一、不选择基本数据类型,而在 Model 里永恒多加二个点 <input
type=”text” ng-modal=”someObj.greeting”/>
变成对象情势 在线编辑代码请点击

 化解方案二、在子 Scope 中使用 $parent.greeting 这将堵住子 Scope
创设它本身的脾性。 在线编辑代码请点击

AngularJS 作用域Scope的继承

末段一点:

delete childScope.anArraychildScope.anArray[1] === 22 // true

若果大家先删除了子功用域childScope的性能,然后再读取该属性,因为找不到该属性,原型链将被询问。

after deleting a property

AngularJS 作用域Scope的继承
**提示:
以下措施会创设新的子功效域,并且进行原型承袭:
ng-repeat、ng-include、ng-switch、ng-view、ng-controller, 用scope:
true
和transclude: true
创制directive。以下方法会创制新的独自作用域,不会进展原型承袭:用scope:
{ … }成立directive。那样创造的成效域被称呼”Isolate”作用域。

注意:暗中同意情状下开创directive使用了scope:
false,不会创制子功效域。实行原型承继即表示父成效域在子功能域的原型链上,那是JavaScript的特点。AngularJS的功能域还存在如下内部定义的关系:
scope.$parent指向scope的父效率域;
scope.$$childHead指向scope的第八个头功用域;
scope.$$childTail指向scope的终极三个子效能域;
scope.$$nextSibling指向scope的下一个相邻功效域;
scope.$$prevSibling指向scope的上二个相邻效率域;

那么些关乎用于AngularJS内部历遍,如$broadcast和$emit事件广播,$digest管理等。
ng-include
In controller:

$scope.myPrimitive = 50;$scope.myObject = {aNumber: 11};

In HTML:

<script type="text/ng-template" id="/tpl1.html"> <input ng-model="myPrimitive"></script><div ng-include src="'/tpl1.html'"></div><script type="text/ng-template" id="/tpl2.html"> <input ng-model="myObject.aNumber"></script><div ng-include src="'/tpl2.html'"></div>

每多个ng-include指令都成立一个子功效域, 并且会从父成效域举行原型承继。

ng-include

在首先个input框输入”77″将会促成子功效域中新建多少个同名属性,其值为77,那不是您想要的结果。

ng-include primitive

在其次个input框输入”99″会一向改换父功效域的myObject对象,那正是JavaScript原型承继机制的成效。

ng-include object

(注:上海体育场地存在错误,珍珠白99因为是50,11应该是99)
假诺大家不想把model由原始类型改成引用类型——对象,我们也能够行使$parent直接操作父作用域:

<input ng-model="$parent.myPrimitive">

输入”22″大家取得了想要的结果。

ng-include $parent

另一种格局正是行使函数,在父功效域定义函数,子作用域通过原型继承可运转该函数:
// in the parent scope

$scope.setMyPrimitive = function(value) { $scope.myPrimitive = value;}

   三、JavaScript原型承接

 假若父类 parentScope 有如下成员属性 aString, aNumber, anArray,
anObject, 以及 aFunction。子类 childScope 原型承继父类
parentScope,于是大家有

美高梅开户网址 21

假诺子 Scope 尝试去拜访 parentScope 中定义的属性,JavaScript 会先在子
Scope 中搜索,如果未有该属性,则找它三番五次的 scope
去获取属性,如若后续的原型对象 parentScope
中都从不应当属性,那么继续在它的原型中查找,从原型链一向往上直到抵达rootScope。所以,下边包车型客车表明式结果都以 true:

childScope.aString === 'parent string'
childScope.anArray[1] === 20
childScope.anObject.property1 === 'parent prop1'
childScope.aFunction() === 'parent output'

固然我们实施上面包车型客车言语

childScope.aString = 'child string'

原型链并未被询问,反而是在 childScope 中扩大了三个新属性
aString。那个新属性隐藏(覆盖)了 parentScope
中的同名属性。在上边大家谈谈 ng-repeat 和 ng-include 时那个概念很关键。

美高梅开户网址 22

childScope.anArray[1] = '22'
childScope.anObject.property1 = 'child prop1'

原型链被询问了,因为对象 anArray 和 anObject 在 childScope
中绝非找到。它们在 parentScope 中被找到了,并且值被更新。childScope
中未有扩大新的特性,也尚未别的新的靶子被创制。(注:在 JavaScript
中,array 和 function 都是指标)

美高梅开户网址 23  

如果我们推行那么些操作:

childScope.anArray = [100, 555]
childScope.anObject = { name: 'Mark', country: 'USA' }

原型链未有被询问,并且子 Scope
新参与了七个新的靶子属性,它们隐藏(覆盖)了 parentScope
中的同名对象属性。

美高梅开户网址 24  

有道是能够总括

  • 只要读取
    childScope.propertyX,并且 childScope 有性能propertyX,那么原型链没有被询问。
  • 如若设置
    childScope.propertyX,原型链不会被询问。

最后一种情景

delete childScope.anArray
childScope.anArray[1] === 22  // true

小编们从 childScope
删除了质量,则当大家再次走访该属性时,原型链会被询问。删除对象的品质会让来自原型链中的性质呈现出来。

美高梅开户网址 25

提示:

  • 以下方法会创制新的子成效域,并且进行原型承接:
    ng-repeatng-includeng-switchng-viewng-controller,
    scope:truetransclude:true创建directive。
  • 以下形式会创设新的独立成效域,不会举办原型承继:用scope:{...}创立directive。这样创造的成效域被誉为”Isolate”功效域。

注意:暗许情况下创办directive使用了scope:false,不会创制子成效域。

张开原型承继即意味着父成效域在子作用域的原型链上,那是JavaScript的性状。AngularJS的效能域还留存如下内部定义的关联:

  • scope.$parent指向scope的父效能域;
  • scope.$$childHead指向scope的率先身长效能域;
  • scope.$$childTail指向scope的末尾一个子成效域;
  • scope.$$nextSibling指向scope的下八个相邻功能域;
  • scope.$$prevSibling指向scope的上三个相邻功能域;

这个涉及用于AngularJS内部历遍,如$broadcast和$emit事件广播,$digest处理等。

请参考:

sample
fiddle
that uses this “parent function” approach. (This was part of a Stack
Overflow
post.)
http://stackoverflow.com/a/13782671/215945
https://github.com/angular/angular.js/issues/1267.
ng-switch
ng-switch与ng-include一样。
参考: AngularJS, bind scope of a
switch-case?
ng-view
ng-view与ng-include一样。
ng-repeat
ng-repeat
也制造子成效域,但有一些分歧。
In controller:

$scope.myArrayOfPrimitives = [ 11, 22 ];$scope.myArrayOfObjects = [{num: 101}, {num: 202}]

In HTML:

<ul><li ng-repeat="num in myArrayOfPrimitives"> <input ng-model="num"> </li></ul><ul><li ng-repeat="obj in myArrayOfObjects"> <input ng-model="obj.num"> </li></ul>

ng-repeat
对每二个迭代项Item都会成立子功用域, 子效率域也从父成效域举行原型承继。
但它依旧会在子功用域中新建同名属性,把Item赋值给相应的子功能域的同名属性
上边是AngularJS中ng-repeat的一对源代码:

childScope = scope.$new(); // child scope prototypically inherits from parent scope ... childScope[valueIdent] = value; // creates a new childScope property

一旦Item是原始类型(如myArrayOfPrimitives的11、22),
那么子成效域中有多个新属性(如num),它是Item的别本(11、22).
修改子效率域num的值将不会退换父效能域myArrayOfPrimitives,所以在上二个ng-repeat,每一个子成效域都有三个num
属性,该属性与myArrayOfPrimitives非亲非故系:

ng-repeat primitive

总来说之那不会是你想要的结果。大家要求的是在子功用域中期维修改了值后反映到myArrayOfPrimitives数组。我们需求动用引用类型的Item,如上边首个ng-repeat所示。
myArrayOfObjects的各样Item都以三个目的——引用类型,ng-repeat对每四个Item创造子成效域,并在子效率域新建obj属性,obj属性正是该Item的二个引用,而不是别本。

ng-repeat object

我们修改子效用域的obj.num正是修改了myArrayOfObjects。那才是大家想要的结果。
**参考:
Difficulty with ng-model, ng-repeat, and
inputs
ng-repeat and
databinding
ng-controller
选拔ng-controller与ng-include同样也是创办子功能域,会从父级controller创造的成效域进行原型传承。不过,利用原型传承来使老爹和儿子controller共享数据是二个不佳的措施。
“it is considered bad form for two controllers to share information via
$scope
inheritance”,controllers之间应当利用
service实行多中国少年共产党享。
(如若一定要动用原型传承来开始展览父亲和儿子controllers之间数据共享,也能够直接使用。
请参照他事他说加以考查: Controller load order differs when loading or
navigating)
directives
暗中认可 (scope: false) –
directive使用原有成效域,所以也不设有原型承继,这种格局很轻易,但也很轻松出难题——除非该directive与html不设有多少绑定,不然一般景色提议采取第2条办法。
scope: true

  • directive创设三个子效率域, 并且会从父作用域进行原型承袭。
    要是同贰个DOM
    element存在八个directives供给创造子功用域,那么唯有多个子功能域被创建,directives共用该子功能域。
    scope: { … }
  • directive创造一个独门的“Isolate”成效域,未有原型承继。那是创制可复用directive组件的最好选项。因为它不会一向访问/修改父效能域的天性,不会发出意想不到的副成效。这种directive与父功效域举办多少通讯有如下八种方法(更详实的开始和结果请参见Developer
    Guide):
    = or =attr
    “Isolate”成效域的质量与父成效域的品质进行双向绑定,任何一方的修改均影响到对方,那是最常用的主意;
    @ or @attr
    “Isolate”成效域的质量与父效率域的性质实行单向绑定,即“Isolate”功能域只好读取父功用域的值,并且该值永恒的String类型
    & or &attr
    “Isolate”效能域把父作用域的习性包装成一个函数,从而以函数的主意读写父效能域的属性,包装格局是$parse,详细情况请见API-$parse;

“Isolate”效率域的proto是四个规范Scope
object (the picture below needs to be updated to show an orange ‘Scope’
object instead of an ‘Object’).
“Isolate”作用域的$parent同样指向父作用域。它纵然从未原型承袭,但它仍旧是二个子功用域。
如下directive:

 <my-directive interpolated="{{parentProp1}}" twowayBinding="parentProp2"> 

scope:

 scope: { interpolatedProp: '@interpolated', twowayBindingProp: '=twowayBinding' }

link函数中:

 scope.someIsolateProp = "I'm isolated"

isolate scope

请留意,大家在link函数中运用attrs.$observe(‘interpolated’,
function(value) { … }来监测@属性的浮动。
越多请参照他事他说加以考察:
http://onehungrymind.com/angularjs-sticky-notes-pt-2-isolated-scope/

transclude: true

   四、AngularJS 的 Scope 继承

  • 创办新的 Scope,并且原型继承:ng-repeat, ng-include, ng-switch, ng-view,
    ng-controller, directive with scope: true, directive
    with transclude: true
  • 始建新的 Scope,但不延续:directive
    with scope: { ... }。它会创设四个独立 Scope。

注:默许意况下 directive 不创建新 Scope,即默许参数是 scope: false

ng-include  借使在大家的 controller 中

$scope.myPrimitive = 50;
$scope.myObject    = {aNumber: 11};

HTML 为:

<script type="text/ng-template" id="/tpl1.html">
    <input ng-model="myPrimitive">
</script>
<div ng-include src="'/tpl1.html'"></div>

<script type="text/ng-template" id="/tpl2.html">
    <input ng-model="myObject.aNumber">
</script>
<div ng-include src="'/tpl2.html'"></div>

每一个 ng-include 会生成三个子 Scope,各种子 Scope 都一而再父 Scope。

美高梅开户网址 26

输入(比方”77″)到第三个 input 文本框,则子 Scope 将获取二个新的
myPrimitive 属性,覆盖掉父 Scope 的同名属性。那说不定和您预想的不平等。

美高梅开户网址 27

输入(比如”99″)到第四个 input 文本框,并不会在子 Scope
创设新的属性,因为 tpl2.html 将 model 绑定到了贰个指标属性(an object
property),原型承接在那时发挥了效益,ngModel 搜索指标 myObject
并且在它的父 Scope 中找到了。

美高梅开户网址 28  

一经大家不想把 model 从 number 基础项目改为对象,我们得以用 $parent
改写第三个模板:

<input ng-model="$parent.myPrimitive">

输入(比如”22″)到那些文本框也不会创设新性情了。model 被绑定到了父 scope
的属性上(因为 $parent 是子 Scope 指向它的父 Scope 的叁本性质)。

美高梅开户网址 29

对于具有的 scope (原型承继的大概非继承的),Angular 总是会经过 Scope 的
$parent, $$childHead 和 $$childTail
属性记录父-子关系(也便是后续关系),图中为简化而未画出那几个属性。

在未曾表单成分的景况下,另一种方法是在父 Scope
中定义三个函数来修改基本数据类型。因为有原型承继,子 Scope
确定保障能够调用那个函数。比如,

// 父 Scope 中
$scope.setMyPrimitive = function(value) {
    $scope.myPrimitive = value;
}

查看
DEMO。参考 StackOverflow。 

ng-include

In controller:

$scope.myPrimitive =50;  $scope.myObject    ={aNumber:11};

In HTML:

<scripttype="text/ng-template"id="/tpl1.html"><input ng-model="myPrimitive"></script><divng-includesrc="'/tpl1.html'"></div><scripttype="text/ng-template"id="/tpl2.html"><input ng-model="myObject.aNumber"></script><divng-includesrc="'/tpl2.html'"></div>

每一个ng-include指令都创造贰个子效率域, 并且会从父作用域进行原型继承。

美高梅开户网址 30

在第二个input框输入”77″将会促成子功用域中新建叁个同名属性,其值为77,那不是你想要的结果。

美高梅开户网址 31

在第贰个input框输入”99″会一贯改造父成效域的myObject指标,这正是JavaScript原型承继机制的功用。

美高梅开户网址 32

(注:上图存在不当,紫罗兰色99因为是50,11相应是99)

如果我们不想把model由原始类型改成引用类型——对象,我们也能够利用$parent直接操作父效用域:

<inputng-model="$parent.myPrimitive">

输入”22″大家赢得了想要的结果。

美高梅开户网址 33

另一种方法正是选取函数,在父功能域定义函数,子作用域通过原型承继可运转该函数:

// in the parent scope  $scope.setMyPrimitive =function(value){      $scope.myPrimitive = value;}

请参考:

sample fiddle that uses this “parent function” approach. (This was part
of a Stack Overflow post.)

.

– directive新建三个“transcluded”子成效域,并且会从父成效域举行原型承继。须求专注的是,“transcluded”成效域与“Isolate”效率域是周围的涉及(假若“Isolate”功效域存在的话)

他们的$parent属性指向同一个父作用域。“Isolate”作用域的$$nextSibling指向“transcluded”作用域。  
更多请参考: [AngularJS two way binding not working in directive
with transcluded
scope](https://link.jianshu.com?t=http://stackoverflow.com/a/14484903/215945)  

transcluded scope


demo:
[fiddle](https://link.jianshu.com?t=http://jsfiddle.net/mrajcok/7g3QM/)

ng-switch

ng-switch 的原型承继和 ng-include
同样。所以倘使您需求对骨干类型数据举行双向绑定,使用
$parent,可能将其改为 object 对象并绑定到对象的质量,防止子 Scope 覆盖父
Scope 的质量。

参考 AngularJS, bind
scope of a
switch-case?

ng-switch

ng-switchng-include一样。

参考: AngularJS, bind scope of a switch-case?

总结

AngularJS存在各样功效域:
一般性的带原型承继的意义域 — ng-include, ng-switch, ng-controller,

ng-repeat

ng-repeat 有好几差异。假使在大家的 controller 里:

$scope.myArrayOfPrimitives = [ 11, 22 ];
$scope.myArrayOfObjects    = [{num: 101}, {num: 202}]

还有 HTML:

<ul>
    <li ng-repeat="num in myArrayOfPrimitives">
       <input ng-model="num">
    </li>
<ul>
<ul>
    <li ng-repeat="obj in myArrayOfObjects">
       <input ng-model="obj.num">
    </li>
<ul>

对于每贰个 Item,ng-repeat 创设新的 Scope,每四个 Scope 都卫冕父
Scope,但同临时候 item 的值也被赋给了新 Scope
的新属性(新属性的名为循环的变量名)。Angular ng-repeat
的源码实际上是那样的:

childScope = scope.$new(); // 子 scope 原型继承父 scope ...     
childScope[valueIdent] = value; // 创建新的 childScope 属性

若是 item 是叁个基础数据类型(就如myArrayOfPrimitives),本质上它的值被复制了一份赋给了新的子 scope
属性。更换这么些子 scope 属性值(比如用 ng-model,即 num)不会改造父
scope 引用的 array。所以地点第二个 ng-repeat 里每一个子 scope
得到的 num 属性独立于 myArrayOfPrimitives 数组:

美高梅开户网址 34

这么的 ng-repeat 和您预想中的分化样。在 Angular 1.0.2
及更早的本子,向文本框中输入会改造鲜绿格子的值,它们只在子 Scope
中可知。Angular 1.0.3+
现在,输入文本不会再有其余意义了。(参照他事他说加以考察 StackOverflow
上的讲解)大家意在的是输入能改换myArrayOfPrimitives 数组,而不是子 Scope 里的品质。为此我们务必将 model
改为二个关于目的的数组(array of objects)。

因此只要 item
是三个目的,则对此原对象的一个引用(而非拷贝)被赋给了新的子 Scope
属性。退换子 Scope 属性的值(使用 ng-model,即 obj.num)也就改造了父
Scope 所引用的目的。所以地点第四个 ng-repeat 可代表为:

美高梅开户网址 35

ng-view

ng-viewng-include一样。

directive with scope: true;普通的带原型承接的,并且有赋值行为的成效域

ng-repeat,ng-repeat为每多个迭代项创立三个数见不鲜的有原型承接的子成效域,但与此同临时间在子作用域中创建新天性存款和储蓄迭代项;“Isolate”成效域
— directive with scope: {…}, 该效率域未有原型承接,但足以经过’=’,
‘@’, 和 ‘&’与父功能域通讯。“transcluded”成效域 — directive with
transclude:
true,它也是平日的带原型承接的作用域,但它与“Isolate”成效域是隔壁的好很好的朋友。

Diagrams were generated with
GraphViz “*.dot”
files, which are on
github.
Tim Caswell’s “Learning JavaScript with Object
Graphs”
was the inspiration for using GraphViz for the diagrams.
The above was originally posted on
StackOverflow.

ng-controller

行使 ng-controller 举行嵌套,结果和 ng-include 和 ng-switch
同样是正规的原型承接。所以做法也一致不再赘述。但是“三个 controller 使用
$scope 承袭来共享消息被以为是倒霉的做法”(来自 这里),应该使用
service 在 controller 间共享数据。

如若你实在要通过一连来共享数据,那么也没怎么出格要做的,子 Scope
能够直接待上访问具有父 Scope 的品质。参考 Controller load
order differs when loading or
navigating

 

directives 分意况研究

  1. 默认 scope: false – directive 不会创建新的
    Scope,所以并未有原型承接。那看起来很简单,但也很凶险,因为您会以为directive 在 Scope
    中创立了三个新的质量,而实际它只是选用了三个已存在的性质。那对编写可复用的模块和组件来讲并倒霉。
  2. scope: true – 那时 directive 会创造二个新的子 scope 并承继父
    scope。假使在同二个 DOM 节点上有多个 directive 都要创设新
    scope,则唯有二个新 Scope 会创设。因为有平日的原型承继,所以和
    ng-include, ng-switch 同样要注意基础项目数据的双向绑定,子 Scope
    属性会覆盖父 Scope 同名属性。
  3. scope: { ... } – 那时 directive 创造三个独自的
    scope,未有原型承继。那在编写制定可复用的模块和零部件时是相比好的精选,因为
    directive 不会十分大心读写父 scope。不过,有时候那类 directives
    又平常索要拜访父 scope 的质量。对象散列(object
    hash)被用来树立这几个独自 Scope 与父 Scope 间的双向绑定(使用
    ‘=’)或单向绑定(使用 ‘@’)。还大概有一个 ‘&’ 用来绑定父 Scope
    的表明式。那几个统统从父 Scope 派生创造出地方的 Scope 属性。注意,HTML
    属性被用来确立绑定,你不可能在指标散列中援引父 Scope
    的属性名,你必须利用二个 HTML
    属性。比如,<div my-directive> 和 scope: { localProp: '@parentProp' } 是无能为力绑定父属性
    parentProp 到独门
    scope的,你必须这么内定: <div my-directive the-Parent-Prop=parentProp> 以及 scope: { localProp: '@theParentProp' }。独立的
    scope 中 __proto__ 引用了一个 Scope 对象(下图中的桔清水蓝Object),独立 scope 的 $parent 指向父
    scope,所以就算它是独自的还要尚未从父 Scope 原型承接,它依然是四个子
    scope。

    上面包车型地铁图中,大家有 <my-directive interpolated="{{parentProp1}}" twowayBinding="parentProp2">和 scope: { interpolatedProp: '@interpolated', twowayBindingProp: '=twowayBinding' }
    还要,尽管 directive 在它的 link
    函数里做了 scope.someIsolateProp = "I'm isolated"

                      美高梅开户网址 36

在意:在 link
函数中选择 attrs.$observe('attr_name', function(value) { ... } 来获取独立
Scope 用 ‘@’ 符号替换的属性值。举个例子,在 link
函数中有 attrs.$observe('interpolated', function(value) { ... } 值将被设为

  1. scope.interpolatedProp 在 link 函数中是
    undefined,相反scope.twowayBindingProp 在 link 函数中定义了,因为用了
    ‘=’ 符号)
    更加多参照他事他说加以调查 http://onehungrymind.com/angularjs-sticky-notes-pt-2-isolated-scope/

                4.transclude: true – 那时 directive 创造了四个新的
“transcluded” 子 scope,同期继续父
scope。所以若是模板片段中的内容(举个例子那个就要替代 ng-transclude
的剧情)供给对父         Scope 的为主项目数据开始展览双向绑定,使用
$parent,或许将 model 一个对象的性质,防止子 Scope 属性覆盖父 Scope
属性。

transcluded 和单身 scope (假设有)是兄弟关系,每种 Scope 的 $parent
指向同多个父 Scope。当模板中的 scope 和单独 Scope 同临时间存在,独立 Scope
属性 $$nextSibling 将会指向模板中的 Scope。越来越多关于 transcluded scope
的新闻,仿效 AngularJS two way
binding not working in directive with transcluded
scope。

在下图中,假如 directive
和上个图一律,只是多了 transclude: true

美高梅开户网址 37

查看 在线
DEMO,例子里有五个showScope() 函数能够用来检查独立 Scope 和它涉及的 transcluded scope。

ng-repeat

Ng-repeat也开创子成效域,但有个别不一样。

In controller:

$scope.myArrayOfPrimitives =[11,22];  $scope.myArrayOfObjects    =[{num:101},{num:202}]

In HTML:

<ul><ling-repeat="num in myArrayOfPrimitives"><inputng-model="num"></li></ul><ul><ling-repeat="obj in myArrayOfObjects"><inputng-model="obj.num"></li></ul>

ng-repeat对每三个迭代项Item都会创建子功能域,
子效率域也从父成效域进行原型承继。
但它照旧会在子效用域中新建同名属性,把Item赋值给相应的子作用域的同名属性
下面是AngularJS中ng-repeat的一对源代码:

childScope = scope.$new();// child scope prototypically inherits from parent scope ...       childScope[valueIdent]= value;// creates a new childScope property

设若Item是原始类型(如myArrayOfPrimitives的11、22),
那么子效能域中有一个新属性(如num),它是Item的别本(11、22).
修改子成效域num的值将不会改换父效用域myArrayOfPrimitives,所以在上一个ng-repeat,每贰个子成效域都有一个num
属性,该属性与myArrayOfPrimitives无涉及:

美高梅开户网址 38

备受关注那不会是你想要的结果。大家需求的是在子功能域中期维修改了值后反映到myArrayOfPrimitives数组。大家需求选取引用类型的Item,如上面第贰个ng-repeat所示。

myArrayOfObjects的每一种Item都以一个对象——引用类型,ng-repeat对每三个Item创造子作用域,并在子功用域新建obj属性,obj品质就是该Item的三个引用,而不是别本。

美高梅开户网址 39

小编们修改子功效域的obj.num正是修改了myArrayOfObjects。那才是大家想要的结果。

参考:

Difficulty with ng-model, ng-repeat, and inputs

ng-repeat and databinding

  五、归咎计算

累计有各类 Scope:

  1. 常见实行原型传承的 Scope —— ng-include, ng-switch, ng-controller,
    directive with scope: true
  2. 一般说来原型承继的 Scope 但拷贝赋值 —— ng-repeat。 种种 ng-repeat
    的巡回都创设新的子 Scope,并且子 Scope 总是获得新的习性。
  3. 独立的 isolate scope —— directive
    with scope: {...}。它不是原型承袭,但 ‘=’, ‘@’ 和 ‘&’ 提供了走访父
    Scope 属性的建制。
  4. transcluded scope —— directive
    with transclude: true。它也如约原型继承,但它同不时候是任何 isolate
    scope 的男生儿。

对此持有的 Scope,Angular 总是会通过 Scope 的 $parent, $$childHead 和
$$childTail 属性记录父-子关系。

ng-controller

使用ng-controllerng-include一模二样也是创办子成效域,会从父级controller创制的成效域进行原型承接。可是,利用原型传承来使老爹和儿子controller共享数据是叁个不佳的法子。
“it is considered bad form for two controllers to share information via
$scope inheritance”,controllers之间应该使用 service实行数量共享。

(假诺一定要动用原型承袭来进展父子controllers之间数据共享,也能够直接使用。
请参考: Controller load order differs when loading or navigating)

directives

  1. 默认 (scope:false) –
    directive使用原本成效域,所以也不设有原型承袭,这种措施很轻松,但也很轻巧出标题——除非该directive与html不设有多少绑定,否则一般景色建议采取第2条办法。
  2. scope:true – directive创设叁个子成效域,
    并且会从父功效域进行原型承袭。 假诺同几个DOM
    element存在八个directives必要创造子功能域,那么唯有一个子功用域被创制,directives共用该子作用域。
  3. scope:{...}
    directive创制多个单身的“Isolate”成效域,未有原型承袭。那是创造可复用directive组件的最好选取。因为它不会一贯访问/修改父成效域的性质,不会发生意想不到的副成效。这种directive与父成效域实行多少通讯有如下各个格局(更详实的源委请参见Developer
    Guide):

    1. = or =attr
      “Isolate”效能域的属性与父功用域的属性进行双向绑定,任何一方的修改均影响到对方,那是最常用的艺术;
    2. @ or @attr
      “Isolate”成效域的属性与父效率域的质量举办单向绑定,即“Isolate”功用域只能读取父效率域的值,并且该值永久的String类型
    3. & or &attr
      “Isolate”效能域把父作用域的性质包装成一个函数,从而以函数的艺术读写父功用域的本性,包装情势是$parse,详细情形请见API-$parse;

“Isolate”作用域的`__proto__`是一个标准[Scope](http://docs.angularjs.org/api/ng.$rootScope.Scope) object (the picture below needs to be updated to show an orange 'Scope' object instead of an 'Object'). “Isolate”作用域的$parent同样指向父作用域。它虽然没有原型继承,但它仍然是一个子作用域。如下directive:<my-directive interpolated="{{parentProp1}}" twowayBinding="parentProp2">     scope:        scope:{ interpolatedProp:'@interpolated', twowayBindingProp:'=twowayBinding'}    link函数中:        scope.someIsolateProp ="I'm isolated"![isolate scope](http://i.stack.imgur.com/MUxS4.png)请注意,我们在link函数中使用`attrs.$observe('interpolated', function(value) { ... }`来监测`@`属性的变化。更多请参考: http://onehungrymind.com/angularjs-sticky-notes-pt-2-isolated-scope/
  1. transclude:true

    directive新建一个“transcluded”子功能域,并且会从父成效域进行原型承继。需求留意的是,“transcluded”功用域与“Isolate”成效域是左近的关系(假设“Isolate”功效域存在的话)

    她们的$parent属性指向同二个父功能域。“Isolate”效用域的$$nextSibling指向“transcluded”功用域。

    更多请参考: AngularJS two way binding not working in directive with
    transcluded scope

    美高梅开户网址 40

    demo: fiddle

总结

AngularJS存在多种作用域:

  1. 普通的带原型继承的法力域 — ng-include, ng-switch,
    ng-controller, directive with scope:true
  2. 经常的带原型承袭的,并且有赋值行为的作用域 —
    ng-repeatng-repeat为每二个迭代项创立七个惯常的有原型承继的子效率域,但还要在子效用域中创制新特性存款和储蓄迭代项;
  3. “Isolate”作用域 — directive with scope:{...}
    该效率域未有原型传承,但足以经过’=’, ‘@’, 和 ‘&’与父作用域通讯。
  4. “transcluded”作用域 — directive with
    transclude:true,它也是一般的带原型承继的功能域,但它与“Isolate”效用域是相邻的好基友。

Diagrams were generated with GraphViz “*.dot” files, which are on
github. Tim Caswell’s “Learning JavaScript with Object Graphs” was the
inspiration for using GraphViz for the diagrams.

The above was originally posted on StackOverflow.


发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图