在angular中,controller是一个javascript 函数(type/class),被用作扩展除了root scope在外的angular scope()的实例。当我们或者angular通过scope.$new api(http://docs.angularjs.org/api/ng.$rootscope.scope#$new)创建新的child scope时,有一个选项作为方法的参数传入controller(这里没看明白,只知道controller的第一个参数是一个新创建的scope,有绑定parent scope)。这将告诉angular需要联合controller和新的scope,并且扩展它的行为。
controller可以用作:
1.设置scope对象的初始状态。
2.增加行为到scope中。
一、 setting up the initial state of a scope object(设置scope对象的初始状态)
通常,当我们创建应用的时候,我们需要为angular scope设置初始化状态。
angular将一个新的scope对象应用到controller构造函数(估计是作为参数传进去的意思),建立了初始的scope状态。这意味着angular从不创建controller类型实例(即不对controller的构造函数使用new操作符)。构造函数一直都应用于存在的scope对象。
我们通过创建model属性,建立了scope的初始状态。例如:
function greetingctrl ($scope) {$scope.greeting = “hola!”;}
“greetingctrl”这个controller创建了一个叫“greeting”的,可以被应用到模版中的model。
二、 adding behavior to a scope object(在scope object中增加行为)
在angular scope对象上的行为,是以scope方法属性的形式,供模版、视图使用。这行为(behavior)可以修改应用的model。
正如指引的model章节()讨论的那样,任意对象(或者原始的类型)赋值到scope中,成为了model属性。任何附加到scope中的function,对于模版视图来说都是可用的,可以通过angular expression调用,也可以通过ng event handler directive调用(如ngclick)。
三、 using controllers correctly
一般而言,controller不应该尝试做太多的事情。它应该仅仅包含单个视图所需要的业务逻辑(还有点没转过弯了,一直认为controller就是个做转发的……)。
保持controller的简单性,常见办法是抽出那些不属于controller的工作到service中,在controller通过依赖注入来使用这些service。这些东西会在向导的dependency injection services章节中讨论。
不要在controller中做以下的事情:
四、 associating controllers with angular scope objects
我们可以显式地通过scope.$new关联controller和scope对象,或者隐式地通过ngcontroller directive(http://docs.angularjs.org/api/ng.directive:ngcontroller)或者$route service(http://docs.angularjs.org/api/ng.$route)。
1. controller 构造函数和方法的 example
为了说明controller组件是如何在angular中工作的,让我们使用以下组件创建一个小应用:
在我们的模版里面的消息,包含一个到spice model的绑定,默认设置为”very”。根据被单击按钮,将spice model的值设置为”chili”或者” jalapeño”,消息会被数据绑定自动更新。
<!doctype html> <html ng-app> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>spicy-controller</title> <meta content="ie=edge,chrome=1" http-equiv="x-ua-compatible"> <style type="text/css"> .ng-cloak { display: none; } </style> </head> <body class="ng-cloak"> <div ng-controller="spicyctrl"> <button ng-click="chilispicy()">chili</button> <button ng-click="jalapenospicy('jalapeño')">jalapeño</button> <p>the food is {{spice}} spicy!</p> </div> <script src="../angular-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> function spicyctrl($scope) { $scope.spice = "very"; $scope.chilispicy = function() { $scope.spice = "chili"; }; $scope.jalapenospicy = function(val) { this.spice = val; }; } </script> </body> </html>
在上面例子中需要注意的东东:
controller方法可以带参数的,正如下面例子所示:
<!doctype html> <html ng-app> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>controller-method-aruments</title> <meta content="ie=edge,chrome=1" http-equiv="x-ua-compatible"> <style type="text/css"> .ng-cloak { display: none; } </style> </head> <body class="ng-cloak"> <div ng-controller="spicyctrl"> <input ng-model="customspice" value="wasabi"/> <button ng-click="spicy(customspice)">customspice</button> <br/> <button ng-click="spicy('chili')">chili</button> <p>the food is {{spice}} spicy!</p> </div> <script src="../angular-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> function spicyctrl($scope) { $scope.spice = "very"; $scope.spicy = function(spice) { $scope.spice = spice; }; } </script> </body> </html>
注意那个spicyctrl controller现在只定义了一个有一个参数”spice”、叫”spicy”的方法。template可以引用controller方法并为它传递常量字符串或model值。
controller继承在angular是基于scope继承的。让我们看看下面的例子:
<!doctype html> <html ng-app> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>controller-inheritance</title> <meta content="ie=edge,chrome=1" http-equiv="x-ua-compatible"> <style type="text/css"> .ng-cloak { display: none; } </style> </head> <body class="ng-cloak"> <div ng-controller="mainctrl"> <p>good {{timeofday}}, {{name}}!</p> <div ng-controller="childctrl"> <p>good {{timeofday}}, {{name}}!</p> <p ng-controller="babyctrl">good {{timeofday}}, {{name}}!</p> </div> </div> <script src="../angular-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> function mainctrl($scope) { $scope.timeofday = 'main时间'; $scope.name = 'main名称'; } function childctrl($scope) { $scope.name = 'child名称'; } function babyctrl($scope) { $scope.timeofday = 'baby时间'; $scope.name = 'baby名称'; } </script> </body> </html>
注意我们如何嵌套3个ngcontroller directive到模版中的。为了我们的视图,这模版结构将会导致4个scope被创建:
继承的工作,在controller和model中是一样的。所以我们前一个例子中,所有model可以通过controller被重写。
注意:在两个controller之间标准原型继承不是如我们所想地那样工作的,因为正如我们之前提到的,controller不是通过angular直接初始化的,但相反地,apply了那个scope对象。(controllers are not instantiated directly by angular, but rather are applied to the scope object,这里跟之前一样,我还是没理解。)
五、 testing controller
虽然有很多方法去测试controller,最好的公约之一,如下面所示,需要注入$rootscope和$controller。(测试需要配合jasmine.js)
<!doctype html> <html ng-app> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>controller-test</title> <meta content="ie=edge,chrome=1" http-equiv="x-ua-compatible"> <link rel="stylesheet" href="../jasmine.css"> <style type="text/css"> .ng-cloak { display: none; } </style> </head> <body class="ng-cloak"> <script src="../angular-1.0.1.js" type="text/javascript"></script> <script src="../angular-scenario-1.0.1.js" type="text/javascript"></script> <script src="../jasmine.js" type="text/javascript"></script> <script src="../jasmine-html.js" type="text/javascript"></script> <script src="../angular-mocks-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> function mycontroller($scope) { $scope.spices = [ {"name":"pasilla", "spiciness":"mild"}, {"name":"jalapeno", "spiceiness":"hot hot hot!"}, {"name":"habanero", "spiceness":"lava hot!!"} ]; $scope.spice = "habanero"; } describe("mycontroller function", function () { describe("mycontroller", function () { var scope; beforeeach(inject(function ($rootscope, $controller) { scope = $rootscope.$new(); var ctrl = $controller(mycontroller, {$scope:scope}); })); it('should create "cpices" model with 3 spices', function () { expect(scope.spices.length).tobe(3); }); it('should set the default value of spice', function () { expect(scope.spice).tobe("habanero"); }); }); }); (function () { var jasmineenv = jasmine.getenv(); jasmineenv.updateinterval = 1000; var trivialreporter = new jasmine.trivialreporter(); jasmineenv.addreporter(trivialreporter); jasmineenv.specfilter = function (spec) { return trivialreporter.specfilter(spec); }; var currentwindowonload = window.onload; window.onload = function () { if (currentwindowonload) { currentwindowonload(); } execjasmine(); }; function execjasmine() { jasmineenv.execute(); } })(); </script> </body> </html>
如果我们需要测试嵌套的controller,我们需要在test中创建与dom里面相同的scope继承关系。
<!doctype html> <html ng-app> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>controller-test</title> <meta content="ie=edge,chrome=1" http-equiv="x-ua-compatible"> <link rel="stylesheet" href="../jasmine.css"> <style type="text/css"> .ng-cloak { display: none; } </style> </head> <body class="ng-cloak"> <script src="../angular-1.0.1.js" type="text/javascript"></script> <script src="../angular-scenario-1.0.1.js" type="text/javascript"></script> <script src="../jasmine.js" type="text/javascript"></script> <script src="../jasmine-html.js" type="text/javascript"></script> <script src="../angular-mocks-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> function mainctrl($scope) { $scope.timeofday = 'main时间'; $scope.name = 'main名称'; } function childctrl($scope) { $scope.name = 'child名称'; } function babyctrl($scope) { $scope.timeofday = 'baby时间'; $scope.name = 'baby名称'; } describe("mycontroller", function () { var mainscope,childscope,babyscope; beforeeach(inject(function ($rootscope, $controller) { mainscope = $rootscope.$new(); var mainctrl = $controller(mainctrl, {$scope:mainscope}); childscope = mainscope.$new(); var childctrl = $controller(childctrl, {$scope:childscope}); babyscope = childscope.$new(); var babyctrl = $controller(babyctrl, {$scope:babyscope}); })); it('should have over and selected', function () { expect(mainscope.timeofday).tobe("main时间"); expect(mainscope.name).tobe("main名称"); expect(childscope.timeofday).tobe("main时间"); expect(childscope.name).tobe("child名称"); expect(babyscope.timeofday).tobe("baby时间"); expect(babyscope.name).tobe("baby名称"); }); }); (function () { var jasmineenv = jasmine.getenv(); jasmineenv.updateinterval = 1000; var trivialreporter = new jasmine.trivialreporter(); jasmineenv.addreporter(trivialreporter); jasmineenv.specfilter = function (spec) { return trivialreporter.specfilter(spec); }; var currentwindowonload = window.onload; window.onload = function () { if (currentwindowonload) { currentwindowonload(); } execjasmine(); }; function execjasmine() { jasmineenv.execute(); } })(); </script> </body> </html>
以上就是关于 angularjs understanding the controller component的资料整理,后续继续补充相关资料,谢谢大家的支持!
如对本文有疑问, 点击进行留言回复!!
基于Angular 8和Bootstrap 4实现动态主题切换的示例代码
解决三元运算符 报错“SyntaxError: can''t assign to conditional expression”
解决angular 使用原生拖拽页面卡顿及表单控件输入延迟问题
使用 Angular RouteReuseStrategy 缓存(路由)组件的实例代码
分享Angular http interceptors 拦截器使用(推荐)
网友评论