在这篇文章中,我们将会研究一下,在控制器中显式地声明数据模型对我们的编程都有哪些好处,在这个过程中有哪些需要我们注意的地方;好了,废话不多说,进入主题吧!
需要知道的知识
ng-controller
是一个特殊的指令,它会以父级作用域(一般为$rootScope
或者另外一个ng-controller
的作用域)为原型生成一个子作用域;这种继承的机制可以创建一个隔离层,用来将需要协同工作的方法和数据模型对象放置在一起。
JavaScript 的对象,要么是值复制要么是引用复制。字符串,数字,布尔型变量都是值复制;数组,对象,函数都是引用复制。
在控制器中使用裸值
在控制器中,我们不推荐使用裸值形式为一个变量赋值,但是为了说明这个问题,我们尝试使用这种方法去编写我们的程序。
我们创建两个控制器,一个父控制器,一个子控制器;在父控制器和子控制器中分别使用父控制器中的数据,然后在父控制器和子控制器中分别修改我们使用的数据,看看会发生什么?
代码如下所示
HTML代码:
html
<div ng-app="MyApp"> <div ng-controller="ParentController"> <h3>Parent Section: {{name}}</h3><br/> <button ng-click="parentChangeName()">parentChangeName</button> <div ng-controller="ChildController"> <h3>Child Section: {{name}}</h3><br/> <button ng-click="childChangeName()">childChangeName</button> </div> </div> </div>
JS代码:
javascript
angular.module("MyApp", []) .controller("ParentController", function($scope){ $scope.name = "dreamapple"; $scope.parentChangeName = function(){ $scope.name = "parent dreamapple"; } }) .controller("ChildController", function($scope){ $scope.childChangeName = function(){ $scope.name = "child dreamapple"; } });
关于上面的代码,我们还是要好好地分析一下:
首先它的表现结果是这样的:
(1)假如我们刚开始点击的是parentChangeName按钮,那么,父控制器和子控制器的h3
标签中的{{name}}
值都将是parent dreamapple
;然后我们点击childChangeName按钮,会发现,只有子控制器的h3
标签中的{{name}}
值发生了变化,变成了child dreamapple
;父控制器里面的{{name}}
没有发生变化。
(2)假如我们刚开始的时候先点击的是childChangeName按钮,那么结果与刚才的不一样,只有子控制器的h3
标签中的{{name}}
值发生了变化,变成了child dreamapple
;父控制器里面的{{name}}
没有发生变化。然后当我们点击parentChangeName按钮时也只有父控制器里面的{{name}}
的值发生了变化。子控制器也没有发生变化。
因为是这样的,由于原型继承的关系,初始化状态下,我们的子控制器虽然有自己的作用域,但是里面的属性值和方法,与父控制器的是一样的;所以,在子控制器有任何操作之前,子控制器里面的属性值与父控制器里面是一样的,所以当点击parentChangeName按钮时,父控制器里面的属性值发生变化,所以子控制器里面的属性值也发生了变化。但是,当我们再次点击childChangeName按钮时,这时候子控制器因为有自己的作用域,所以只能够修改自己作用域里的属性值,无法修改父控制器作用域里面的属性值。
第二种情况也很好解释,因为一开始,点击childChangeName按钮就修改了子作用域的属性值,虽然我们紧接着点击了parentChangeName按钮但是却没有改变子作用域里面的属性值,因为点击parentChangeName按钮只能在初始化的时候(并且子作用域中没有对那个属性进行初始化Online Code Part2),改变父控制器和子控制器的属性值,如果子控制器里面的属性已经被修改或者初始化了,那么父控制器也不可以改变子控制器里面的属性值。
在控制器中显式声明数据模型
我们将修改上面的代码,不再使用裸值,而是显式的声明一个对象。
代码部分如下
HTML代码:
html
<div ng-app="MyApp"> <div ng-controller="ParentController"> <h3>Parent Section: {{person.name}}</h3><br/> <button ng-click="parentChangeName()">parentChangeName</button> <div ng-controller="ChildController"> <h3>Child Section: {{person.name}}</h3><br/> <button ng-click="childChangeName()">childChangeName</button> </div> </div> </div>
JS代码:
javascript
angular.module("MyApp", []) .controller("ParentController", function($scope){ // $scope.name = "dreamapple"; $scope.person = { name: "dreamapple" }; $scope.parentChangeName = function(){ // $scope.name = "parent dreamapple"; $scope.person.name = "parent dreamapple"; } }) .controller("ChildController", function($scope){ $scope.childChangeName = function(){ // $scope.name = "child dreamapple"; $scope.person.name = "child dreamapple"; } });
我们来看看它的表现结果:
这时你会发现,不论是点击parentChangeName按钮还是点击childChangeName按钮,父控制器和子控制器里面的{{name}}
都会发生变化,这是为什么呢?
因为,首先我们在父作用域上创建了一个对象也就是一个数据模型,子控制器上也会有对这个对象的引用,所以无论我们改变哪一个控制器里这个对象的属性,都会反应到这两个控制器里面。
到这里,我想要和大家分享的差不多快结束了,不过还有一点需要注意的,就是使用任何会创建子作用域指令时,如果将指令定义中的scope
设置为true
,都会有上面的特性,我们可以根据自己的需要,采取不同的方法;好了,差不多该睡午觉了,还有,如果大家觉得我哪里说得不对,还望指出,我们一起进步。