scope的继承
本文转载自: http://www.tuicool.com/articles/63iEref
angular中scope的继承与js的原型继承有密切的联系,首先回顾一下js的继承:
function ParentScope(){
this.aString = "parent string";
this.aNumber = 100;
this.anArray = [10,20,30];
this.anObject = {
'property1': 'parent prop1',
'property2': 'parent prop2'
};
this.aFunction = function(){
return 'parent output';
}
} function ChildScope(){
} ChildScope.prototype = new ParentScope();
ChildScope.prototype.constructor= ParentScope;
var childScope = new ChildScope();
ChildScope继承自ParentScope,关系图如下:
如果我们要在 childScope 上查询一个定义在 parentScope 的属性, JavaScript 会先在 childScope 上查找, 如果没有查到, 那么会顺着原型链去查找. 所以以下判别式均为 true
childScope.aString === 'parent string'
childScope.anArray[1] === 20
childScope.anObject.property1 === 'parent prop1'
childScope.aFunction() === 'parent output'
接下来做如下操作
childScope.aString= 'child string'
原型链将不会被访问, 一个新的 aString
会被加入到 childScope 的属性中去, 新的属性会隐藏 parentScope 中的同名属性:
再这么做:
childScope.anArray[1]= 10;
childScope.anObject.property1= 'child prop1';
原型链被访问了. 因为 anArray
, anObject
没有在 childScope 中找到.
新的赋值操作均在 parentScope 上进行. childScope 上没有添加任何新的属性.
但如果我们做如下操作:
childScope.anArray= [100, 555];
childScope.anObject= {name: 'Mark', country: 'USA'}
原型链没有被访问, childScope 会获得两个新的属性, 并且会隐藏 parentScope 上的同名属性.
仔细分析, 第一第三次均是对某个属性直接进行赋值, 原型链并不会被访问, 由于属性并不存在, 所以新的属性将会被添加.
而第二次其实是先访问 , 再赋值,原型链就会被打开。
--------------------------------------------------------------------------------------------------------------------------------------------------
再来看Angular scope的继承
以下指令汇创建新的scope,并且在原型上继承父scope
ng-repeat, ng-switch,ng-view,ng-controller
带有scope: true的指令,带有transclude:true的指令
值得注意的是以下指令不会继承父scope
scope: {}的指令,这会创建一个隔离作用域
scope: false ,这会共享作用域
让我们看几个例子:
ng-include
JS:
$scope.myPrimitive = 50;
$scope.myObject = {aNumber: 11};
HTML:
<p>{ myPrimitive }</p>
<p>{ myObject.aNumber }</p> // cannot use double curly brackets in jekyll
<script type="text/ng-template" id="/tpl1.html">
<input type="number" ng-model="myPrimitive">
</script>
<div ng-include src="'/tpl1.html'"></div>
<script type="text/ng-template" id="/tpl2.html">
<input type="number" ng-model="myObject.aNumber">
</script>
<div ng-include src="'/tpl2.html'"></div>
每一个ng-include都会创建一个子scope, 并在原型上继承父scope
向第一个 input 输入数字, 一个新的属性 myPrimitive
将会被创建, 同时隐藏 父 scope 的 myPrimitive
;
向第二个 input 输入数字, 子 scope 并不会创建一个新的属性, 这时候原型继承发挥了作用
第一种情况很可能不是我们期待的结果, 所以可以显式的调用 $parent
来解决这个问题.
<input type= "text" ng-model= "$parent.myPrimitive"/>
向第一个 input 键入数字, 这时候就不会产生新的属性了. $parent 指向了 父scope. 但是 $parent 和 原型上的继承并不一定相等. 稍后我们会看到一个例子.
对于所有的 scope, 无论是共享的( scope: false
), 继承的( scope: true
), 还是孤立的( scope: { ... }
),
Angular 都会建立一个 父-子 的层级关系, 这个层级关系是根据 dom 结构的层级关系决定的, 可以通过 $parent
, $$childHead
, $$childTail
来访问.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ng-switch、ng-view
情况与ng-include一样,不赘述
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ng-repeat
ng-repeat有一些特殊
$scope.myArrayOfPrimitives = [ 11, 22 ];
$scope.myArrayOfObjects = [{num: 101}, {num: 202}]
<ul><li ng-repeat="num in myArrayOfPrimitives">
<input ng-model="num"></input>
</li>
</ul>
<ul><li ng-repeat="obj in myArrayOfObjects">
<input ng-model="obj.num"></input>
</li>
</ul>
对于每一次迭代, ng-repeat 都会创建一个 子scope, 并在原型上继承 父scope, 但是他还会将 父scope 上的属性赋值到 子scope 上 . 新的属性名就是 ng-repeat="** in parentScope.property"
中的 **.
源码中的 ng-repeat 是这样的:
childScope = scope.$new(); // child scope prototypically inherits from parent scope ...
childScope[valueIdent] = value; // creates a new childScope property
如果 ** 是 primitive, 那么一份 copy 会被赋值到新的属性上. 修改 子scope 上的新属性自然不会修改 父 scope 上的属性.
如果 ** 是个 object, 那么一个 reference 会被赋值到新的 子scope 属性上. 修改这个属性, 就是修改 父scope 对应的属性.
ng-controller
ng-controller 也是会创建新的 子scope, 同时原型继承 父scope. 如同 ng-include, ng-switch, ng-view.
但是, 使用 $scope 来共享数据被认为是一种不好的操作. 因为原型链可是会一直向上追溯的.
如果想要共享数据, 最好使用 service
--------------------------------------------------------------------------------------------------------------------------------------
directive
我们来总结以下指令中的 scope:
1.scope: false 指令不会创建新的 scope, 没有继承关系. 与 $parent 共享 $scope
2.scope: true 指令会创建一个 子scope, 并在原型上继承 $parent. 如果在一个 DOM 上有多个指令想要创建新的 scope, 会报错.
3.scope: {...} 指令会创建一个 孤立的scope. 这在创建可重用的组件时是最好的选择. 但是, 即使如此, 指令还是希望读取 $parent 的数据.
transclude
指令创建了一个 “transcluded” 的子scope, 在原型上继承其 父scope. 如果上述例子同时具有 transclude: true
. 那么这个 “transcluded” scope, 和 “islolated” scope 是姊妹关系. 他们的 $parent 指向同一个 scope. 且 isolate scope 的 $$nextSibling 就是这个 “transcluded scope”. 下图反应了他们之间的关系:
scope的继承的更多相关文章
- 精通AngularJS(三)深入scope,继承结构,事件系统和生命周期
深入探讨 Scope 作用域 每一个 $scope 都是类 Scope 的一个实例.类 Scope 拥有可以控制 scope 生命周期的方法,提供事件传播的能力,并支持模板渲染. 作用域的层次结构 让 ...
- angularjs 中的scope继承关系——(2)
转自:http://www.lovelucy.info/understanding-scopes-in-angularjs.html angularjs 中的scope继承关系 ng-include ...
- angularjs中的directive scope配置
angularjs中的directive scope配置 定义directive其中重要的一环就是定义scope,scope有三种形式: 默认的scope,DOM元素上原有的scope scope: ...
- 指令的Link函数和Scope
指令生成出的模板其实没有太多意义,除非它在特定的scope下编译.默认情况下,指令并不会创建新的子scope.更多的,它使用父scope.也就是说,如果指令存在于一个controller下,它就会使用 ...
- 深入理解 AngularJS 的 Scope
JavaScript 的原型继承就是奇葩. 之前在 V2EX 上看到讨论说,不会 OOP 的 JavaScript 的程序员就是野生程序员.看来我是属于野生的. 一.遇到的问题 问题发生在使用 A ...
- 理解AngularJS的作用域Scope
AngularJS中,子作用域一般都会通过JavaScript原型继承机制继承其父作用域的属性和方法.但有一个例外:在directive中使用scope: { ... },这种方式创建的作用域是一个独 ...
- 用AngularJS开发的过程中如何查看Scope内容
scope的继承就好比JS的原型链继承,深入理解Scope:http://www.lovelucy.info/understanding-scopes-in-angularjs.html 通过查看官网 ...
- 深入理解 AngularJS 的 Scope(转)
一.遇到的问题 问题发生在使用 AngularJS 嵌套 Controller 的时候.因为每个 Controller 都有它对应的 Scope(相当于作用域.控制范围),所以 Controller ...
- Angularjs Scope 原型链
我们知道scope是可以继承的.scope的继承和js原型链是同一个概念. <div ng-controller="parentCtrl"> {{name}} < ...
随机推荐
- Servlet 表单数据
很多情况下,需要传递一些信息,从浏览器到 Web 服务器,最终到后台程序.浏览器使用两种方法可将这些信息传递到 Web 服务器,分别为 GET 方法和 POST 方法. GET 方法 GET 方法向页 ...
- Spring4 MVC REST服务使用@RestController实例
在这篇文章中,我们将通过开发使用 Spring4 @RestController 注解来开发基于Spring MVC4的REST风格的JSON服务.我们将扩展这个例子通过简单的注释与JAXB标注域类支 ...
- python 反射机制 ( 广泛应用于URL参数)
web实例 考虑有这么一个场景,根据用户输入的url的不同,调用不同的函数,实现不同的操作,也就是一个url路由器的功能,这在web框架里是核心部件之一.下面有一个精简版的示例: 首先,有一个comm ...
- jvm(13)-线程安全与锁优化
[0]README 0.1)本文部分文字转自“深入理解jvm”, 旨在学习 线程安全与锁优化 的基础知识: 0.2)本文知识对于理解 java并发编程非常有用,个人觉得,所以我总结的很详细: [1]概 ...
- /dev/null简介
在类Unix系统中,/dev/null,或称空设备,是一个特殊的设备文件,它丢弃一切写入其中的数据(但报告写入操作成功),读取它则会立即得到一个EOF[1]. 在程序员行话,尤其是Unix行话中,/d ...
- spring mvc3.1 @ResponseBody注解生成大量Accept-Charset
Spring3 MVC使用@ResponseBody后会产生非常大的响应头(Accept-Charset会达到4K+).原因在于默认情况下StringHttpMessageConverter.writ ...
- HTML+CSS实现简单三级菜单
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Introduction to Mathematical Thinking - Week 4
否定的逻辑 应该思考符号背后表示的逻辑,而不是像操作算术运算符一样操作逻辑符号. 比如 对于任意的 x,x属于自然数,那么 x 是偶数或者奇数:这是对的 如果使用“乘法分配律”拆分,变成“对于任意的x ...
- iOS RunLoop详解
1. RunLoop简介 1.1 什么是RUnLoop 可以理解为字面的意思:Run表示运行,Loop表示循环.结合在一起就是运行的循环.通常叫做运行循环. RunLoop实际上是一个对象,这个对象在 ...
- 数据库时间类型和 util 包下时间类型转换
Java 中的类型 1. java.sql 包下给出三个数据库相关的日期时间类型,分别是 java.sql.Date, 表示日期,只有年月日,没有时分秒. java.sql.Time, 表示时间, 只 ...