理解Angular中的$scope
在AngularJS中,child scope一般通过原型式继承自它的parent scope。(directive的scope属性为{...}的情况除外,因为它会创建独立的scope)。在指令中,默认使用的是parent scope,这意味着在指令中改变的任何属性都会反映到其parent scope中。设置scope:true 会在该指令中使用原型继承。
scope的继承通常是直截了当的,但是当你尝试在child scope中使用定义在parent scope的双向数据绑定的时候,它可能就不像你期望的那样起作用了。原因是child scope会重写parent scope中的重名属性,这是原型式继承的一个特征。
注意:ng-repeat, ng-switch, ng-view, ng-include 都会创建新的child scope,上述问题通常出现在这些指令的使用过程中。具体可以看看这个例子
要避免上面的问题有以下几个方法:
注意,默认情况下,自定义指令并不会创建新的scope,scope:false是默认值
假设在controller.js中有以下代码
// 定义一个基本类型的值 $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都会产生一个新的child scope, 原型继承自parent scope
看看结果如下:
第一个input的ng-model是一个基本类型,它不能与parent scope中的表达式实现双向数据绑定,原因在于child scope通过原型继承属性自其parent scope,对于基本类型的值,child scope重写parent scope中的重名属性。
第二个input的ng-model是一个对象,它可以实现双向数据绑定,当ngModel查找一个对象时,它会一直查找到parent scope.
我们也可以对第一个input进行改写如下:
<input ng-model="$parent.myPrimitive">
这里$parent是child scope下的一个属性,该属性指向parent scope
或者在parent scope中定义一个方法来改变基本类型的值,在child scope调用该方法,看代码
// controller.js $scope.setMyPrimitive = function (value){ $scope.myPrimitive = value; }
<input ng-model="myPrimitive" class="form-control" ng-change="setMyPrimitive(myPrimitive)">
效果如下:可以看到可以正常地进行双向数据绑定了
假设有如下代码:controller.js
$scope.myArrayOfPrimitives = [ 11, 22 ];
$scope.myArrayOfObjects = [{num: 101}, {num: 202}]
html代码如下:
<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>
对每一个li,ng-repeat都创建一个新的scope,继承自parent scope,但是同时会将遍历的变量(第一个ul中为num) 作为新的child scope的一个属性,myArrayOfPrimitives[num]的值作为该属性的属性值。
angular中ng-repeat的源码如下:
childScope = scope.$new(); // child scope prototypically inherits from parent scope ... childScope[valueIdent] = value; // creates a new childScope property
如果在遍历数组中的每个item是一个基本类型(myArrayOfPrimitives),该item的值会被分配给新child scope的属性,改变这个属性的值(例如使用ng-model),不会改变parent scope中的数组。在第一个ul中,每个child scope有一个num属性独立于数组myArrayOfPrimitives。
如果我们希望改变在item中改变parent scope中的数组,我们需要将model变为一个数组对象
所以,如果数组中的每个item都是一个对象,该对象的一个引用会被分配给child scope的属性,改变child scope的属性值也会改变parent scope中的数组的引用。
今天先搞到这里,原文地址Understanding Scopes
优质内容筛选与推荐>>