转自:http://www.lovelucy.info/understanding-scopes-in-angularjs.html

angularjs 中的scope继承关系

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。

输入(比如”77″)到第一个 input 文本框,则子 Scope 将获得一个新的 myPrimitive 属性,覆盖掉父 Scope 的同名属性。这可能和你预想的不一样。

输入(比如”99″)到第二个 input 文本框,并不会在子 Scope 创建新的属性,因为 tpl2.html 将 model 绑定到了一个对象属性(an object property),原型继承在这时发挥了作用,ngModel 寻找对象 myObject 并且在它的父 Scope 中找到了。

如果我们不想把 model 从 number 基础类型改为对象,我们可以用 $parent 改写第一个模板:

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

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

对于所有的 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 是一个基础数据类型(就像 myArrayOfPrimitives),本质上它的值被复制了一份赋给了新的子 scope 属性。改变这个子 scope 属性值(比如用 ng-model,即 num)不会改变父 scope 引用的 array。所以上面第一个 ng-repeat 里每一个子 scope 获得的 num 属性独立于 myArrayOfPrimitives 数组:

这样的 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 可表示为:

这才是我们想要的。输入到文本框即会改变灰色格子的值,该值在父 Scope 和子 Scope 均可见。

总结

一共有四种 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 属性记录父-子关系。

angularjs 中的scope继承关系——(2)的更多相关文章

  1. angularjs 中的scope继承关系——(1)

    转自:http://www.lovelucy.info/understanding-scopes-in-angularjs.html JavaScript 的原型链继承 假设父类 parentScop ...

  2. 理解angularJS中作用域$scope

    angularJS中作用域是什么 作用域(scope)是构成angularJS应用的核心基础,在整个框架中都被广泛使用,因此了解它如何工作是非常重要的 应用的作用域是和应用的数据模型相关联的,同时作用 ...

  3. Programming In Scala笔记-第十一章、Scala中的类继承关系

    本章主要从整体层面了解Scala中的类层级关系. 一.Scala的类层级 在Java中Object类是所有类的最终父类,其他所有类都直接或间接的继承了Object类.在Scala中所有类的最终父类为A ...

  4. AngularJS中监视Scope变量以及外部调用Scope方法

    在AngularJS中,有时候需要监视Scope中的某个变量,因为变量的改变会影响一些界面元素的显示.有时,也希望通过jQuery调用Scope的某个方法. 比如以下场景: <div> & ...

  5. ES6中Class的继承关系

    es5实现中,每个对象都有__proto__属性(也就是关系图中[[prototype]]属性),指向对应的构造函数的prototype.Class 作为构造函数的语法糖,同时有prototype属性 ...

  6. angularjs学习之八(angularjs中isolate scope的使用)

    angular js中指令directive有个特别实用的东西,那就是 isolate scope (被隔离的scope) 关于详细他和全局的scope 有什么差别.能够參考以下这篇博文: Angul ...

  7. cocos2d JS-(JavaScript) JavaScript 中的简单继承关系

    JavaScript 语言本身没有提供类,没有其他语言的类继承机制,它的继承时通过对象的原型实现的,但这不能满足我们对 Cocos2d-JS 引擎的要求,所有类都直接或间接继承实现的. var Per ...

  8. angularjs中使用$scope.$watch监控对象模型的变化

    如果对象模型发生变化时,可以使用$scope.$watch监控变化 <html ng-app="myApp"> <head> <title>an ...

  9. AngularJS中控制器继承

    本篇关注AngularJS中的控制器继承,了解属性和方法是如何被继承的. 嵌套控制器中属性是如何被继承的? ==属性值是字符串 myApp.controller("ParentCtrl&qu ...

随机推荐

  1. Mysql的基本语句

    Mysql的基本语句 1.查询当前数据库所有表名: -- 方案一: show tables; --方案二:jeesite为数据库 select table_name from information_ ...

  2. QTQuick控件基础(3)视图

    1.spliteview 2.stackview ApplicationWindow {visible: truewidth: 640height: 480MouseArea{anchors.fill ...

  3. codevs 1423 骑士 - Tarjan - 动态规划

    题目描述 Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬. 最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵 ...

  4. 定义c/c++全局变量/常量几种方法的区别(转载)

    出自:http://www.cnblogs.com/yaozhongxiao/archive/2010/08/08/1795338.html 在讨论全局变量之前我们先要明白几个基本的概念:  1. 编 ...

  5. 删除string类型字符串中指定字符串段

    1.实现背景 在插入list行时用邮件的MessageID给对应行命名. 在回复全部邮件时,收件人变为之前收件人中出去“自己”同时加入之前发件人,抄送人还是之前的抄送人,密送人不用管,直接不用带. 在 ...

  6. Android widget

    1,TextView :走马灯效果 2,EditText ,AutoCompleteText MutiAutoCompleteTextView 3,Button,ImageButton,RadioBu ...

  7. linux 之awk命令详解

    awk是一种程序语言,对文档资料的处理具有很强的功能.awk名称是由它三个最初设计者的姓氏的第一个字母而命名的: Alfred V. Aho.Peter J. We i n b e rg e r.Br ...

  8. Java propertis文件中组装配置

    目的: 实现在配置文件中,进行组装 1.Properties文件配置如下: dns=http://211.103.227.133:8080 qrcode=${dns}/wx/views/invite/ ...

  9. 【建表】ElasticSearch建表命令

    使用google插件Postman 发送方式为PUT,url地址: 192.168.2.11:9200/IndexName 文本raw,数据为json格式 { "settings" ...

  10. Codeforces 1091 Good Bye 2018

    占个坑先,希望不要掉的太惨了吧,不要掉到上一次之前的rating upt:flag竟然没到,开心. A - New Year and the Christmas Ornament 好像没什么可说的. ...