scope基于原型的继承性
视图存在嵌套的时候,内层的controller是可以继承到外层的controller数据的。
scope在angularjs里的继承性(基于原型的继承性):
html:
<div ng-controller="MainController">
Parent <input type='text' ng-model="info"> {{info}}
<div ng-controller="subController">
child <input type='text' ng-model="info"> {{info}}
</div>
</div>
当页面一开始加载完毕之后,通过在parent
的input
里面输入内容的时候,在child
的input
里面也会发生响应。这个时候,subController
里的info
的值,是继承parent
里面的mainController
的值。
此时,如果在child
的input
里面输入内容,会发现child
里面的info
发生了变化,但是parent
里面并未发生变化。
此时如果在parent
的Input
里面输入值的话,仅仅是Parent
的info
发生了变化,而child
的info
是不会发生变化的。
然后我再换一种写法
html:
<div ng-controller="mainController">
parent <input type="text" ng-model='msg.info'> {{msg.info}}
<div ng-controller="subController">
child <input type="text" ng-model="msg.info"> {{msg.info}}
</div>
</div>
js:
app.controller('mainController', function(){
$scope.msg = {
info: 'message'
};
});
app.controller('subController', function(){
});
ng-model
此时变成了某个对象的属性。那么现在不管你更改的是parent
中的input
还是child
中的input
,都会引起视图相应的变化。
这2者的区别就是在subController
中继承了mainController
中的作用域。当ng-model
是primitive
值时,刚初始化的时候,在subController
里面因为,会新建一个相同的变量,这个时候,如果再在subController
里面获取这个primitive
的时候,就直接在subController
里面就能得到。
而如果mainController
里面的ng-model
是个对象的属性的时候,subController
里面ng-model
是对这个对象的引用。那么不管更改mainController
还是subController
里面的ng-model
视图里面都会发生变化。
在Angularjs里面$scope
有个$watch
方法,当需要时更新DOM。通过监听某个model的是否发生变化来触发相应的callback
。
依然是上面的例子:
html:
<div ng-controller="mainController">
parent <input type="text" ng-model='msg.info'>
</div>
js:
app.controller('mainController', function(){
$scope.msg = {
info: 'message'
};
$scope.$watch('msg', function(val){
console.log(val);
})
});
除了页面初始化后,控制台会输出{info: 'message'}
外,不过input里面的值如何变化。控制台都不会输出任何内容了。这是因为$watch
是比较的msg这个对象的引用是否发生了变化,很显然这个地方msg的引用(heap里面存放的地址)并没用发生变化,仅仅是msg.info的值发生了变化。
但是我改变另外一种写法:
$scope.$watch('msg', function(val){
console.log(val);
}, true);
这个是否就能监听到msg.info
发生变化后,msg
的内容了。第三个属性boolean
值,当为true,规定的是比较对象的值,而不是引用。
ng-repeat
会给每个循环新建一个作用域。
ng-include
和ng-view
都是动态加载视图,这个时候也会新建作用域
当然还有ng-switch
,directive
也会有这种scope
继承的情况出现。
具体深入理解angularjs
的scope
,请移步Understanding scopes
Angularjs 1.2 “Controller as” polyfill
html:
<div ng-controller='parentController as parent'>
{{parent.name}}
<div ng-controller='childController as child'>
{{child.name}}
</div>
</div>
js:
app.controller('parentController', ApiParentFn);
function ApiCtrlFn(){
this.name = 'XL';
}
app.controller('childController', ApiChildFn);
function ApiChildFn(){
this.name = 'xl';
}
最后视图内容大家可以动手试试。
最近也试着多用这个语法去写控制器,首先写法上更偏向OO的风格。在这个ApiParetnFn
上定义不同的model。
app.controller('mainCtrl', ['$http', ApiCtrlFn]);
function ApiCtrlFn(http){
this.http = http;
this.name = 'XL';
}
ApiCtrlFn.prototype = {
reqPostFn: function(url){
this.http.get(url).success(function(data){
xxxx
})
.error(function(data){
xxxx
})
},
changeNameFn: function(name){
this.name = name;
}
}
html:
<div ng-controller="mainCtrl as main">
{{this.name}}
<button ng-click="main.changeNameFn('xl')"></button>
</div>
在ApiParentFn.prototype
上定义不同的方法。这样可以非常好的将一些可服用的代码抽离出来。不同的控制器只需要对构造函数进行实例化,然后调用不同的原型上定义的方法就OK了。