转浓密掌握 AngularJS 的 Scope功效域

小说转载英文:what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs

         
 中文:http://www.lovelucy.info/understanding-scopes-in-angularjs.html

   一、AngularJS 中的 Scope(scope即作用域、功用范围)所涉嫌知识点大致预览图

 图片 1

   二、AngularJS中调节器间嵌套难点

在动用 AngularJS 嵌套 Controller 的时候。因为各个 Controller
都有它对应的 Scope(相当于功能域、调控范围),所以 Controller
的嵌套,也就象征 Scope 的嵌套。

那个时候借使七个 Scope 内都有同名的 Model
会发生什么呢?从子 Scope
怎么着翻新父 Scope 里的 Model 呢?

   二.1父子嵌套调整器scope中属性名同样时(准确说基本数据类型属性名)景况

在AngularJS中子scope会承继父scope中的对象,但当您试下对骨干数据类型(string, number,
boolean)
的 双向数据绑定 时,子 Scope 的性质隐藏(覆盖)了父 Scope 中的同名属性,对子 Scope 属性(表单成分)的改造并不更新父 Scope 属性的值。

图片 2

在线编辑代码  请点击自身啊 那种行为其实不是 AngularJS
特有的,JavaScript 本人的原型链便是这么职业的。

开采者经常都不曾察觉到 ng-repeat,
ng-switch, ng-view 和 ng-include 统统都创立了她们新的子 scopes,所以在用到那么些 directive
时也时不时出标题。

   二.一 子 Scope 怎么样翻新父 Scope 里的
Model 呢?

 消除方案1、不采纳基本数据类型,而在 Model 里长久多加一个点 <input
type=”text” ng-modal=”someObj.greeting”/>
变成对象格局 在线编辑代码请点击

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

   三、JavaScript原型承接

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

图片 3

假诺子 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 时这几个定义很首要。

图片 4

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

原型链被询问了,因为对象 anArray 和 anObject 在 childScope
中从未找到。它们在 parentScope 中被找到了,并且值被更新。childScope
中并未有扩张新的属性,也尚无别的新的靶子被创设。(注:在 JavaScript
中,array 和 function 都以目的)

图片 5  

设若大家实施这几个操作:

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

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

图片 6  

有道是能够计算

  • 壹旦读取
    childScope.propertyX,并且 childScope 有品质propertyX,那么原型链没有被询问。
  • 只要设置
    childScope.propertyX,原型链不会被询问。

最后一种境况

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

笔者们从 childScope
删除了品质,则当大家再度走访该属性时,原型链会被询问。删除对象的性格会让来自原型链中的属性体现出来。

图片 7

   四、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>

每3个 ng-include 会生成3个子 Scope,种种子 Scope 都延续父 Scope。

图片 8

输入(举个例子”7七″)到第叁个 input 文本框,则子 Scope 将获得3个新的
myPrimitive 属性,覆盖掉父 Scope 的同名属性。这恐怕和你预想的不等同。

图片 9

输入(举例”9玖″)到第1个 input 文本框,并不会在子 Scope
制造新的性格,因为 tpl二.html 将 model 绑定到了八个目的属性(an object
property),原型承继在那儿发挥了效果,ngModel 搜索目的 myObject
并且在它的父 Scope 中找到了。

图片 10  

若是咱们不想把 model 从 number 基础项目改为对象,我们能够用 $parent
改写第二个模板:

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

输入(比方”22″)到那些文本框也不会成立新天性了。model 被绑定到了父 scope
的习性上(因为 $parent 是子 Scope 指向它的父 Scope 的二本性子)。

图片 11

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

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

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

查看
DEMO
。参考 StackOverflow。 

ng-switch

ng-switch 的原型继承和 ng-include
同样。所以要是你必要对大旨项目数据开始展览双向绑定,使用
$parent,或然将其改为 object 对象并绑定到对象的质量,防止子 Scope 覆盖父
Scope 的质量。

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

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 是3个基础数据类型(就像myArrayOfPrimitives),本质上它的值被复制了壹份赋给了新的子 scope
属性。退换这么些子 scope 属性值(比方用 ng-model,即 num)不会转移父
scope 引用的 array。所以地点第伍个 ng-repeat 里每2个子 scope
获得的 num 属性独立于 myArrayOfPrimitives 数组:

图片 12

那样的 ng-repeat 和你预想中的不1致。在 Angular 壹.0.2及更早的版本,向文本框中输入会转移葡萄紫格子的值,它们只在子 Scope
中可知。Angular 一.0.3+
以往,输入文本不会再有其它功用了。(参考 StackOverflow
上的说明
)大家愿意的是输入能更换myArrayOfPrimitives 数组,而不是子 Scope 里的脾性。为此大家不可能不将 model
改为三个有关目的的数组(array of objects)。

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

图片 13

ng-controller

运用 ng-controller 进行嵌套,结果和 ng-include 和 ng-switch
一样是常规的原型承继。所以做法也1致不再赘言。可是“多个 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 会成立2个新的子 scope 并一连父
    scope。若是在同1个 DOM 节点上有三个 directive 都要开立异scope,则唯有1个新 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"

                      图片 14

瞩目:在 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

图片 15

查看 在线
DEMO
,例子里有3个showScope() 函数可以用来检查独立 Scope 和它事关的 transcluded scope。

  5、归结计算

总共有各类 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 属性记录父-子关系。

相关文章