AngularJs Understanding the Controller Component
在angular中,controller是一个 javascript 函数 (type/class),被用作扩展除了root scop e在外的angular scop e()的实例。当我们或者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的初始状态。例如:
“GreetingCtrl”这个controller创建了一个叫“greeting”的,可以被应用到模版中的model。
二、 Adding Behavior to a Scope Object(在scope object中增加行为)
在angular scope对象上的行为,是以scope方法属性的形式,供模版、视图使用。这行为(behavior)可以修改应用的model。
正如指引的model章节()讨论的那样,任意对象(或者原始的类型)赋值到s cop e中,成为了model属性 。任何附加到scop e中的function,对于模版视图来说都是可用的,可以通过angular expression调用 ,也可以通过ng event handler directive调用 (如ngClick)。
三、 Using Controllers Correctly
一般而言,controller不应该尝试做太多的事情。它应该仅仅包含单个视图所需要的业务逻辑(还有点没转过弯了,一直认为Controller就是个做转发的……)。
保持Controller的简单性,常见办法是抽出那些不属于controller的工作到service中,在controller通过依赖注入来使用这些service。这些东西会在向导的Dependency Injection Services章节中讨论。
不要在Controller中做以下的事情:
任何类型的DOM操作 - controller应该仅仅包含业务逻辑。DOM操作,即应用的表现逻辑,它的测试难度是众所周知的。将任何表现逻辑放到controller中,大大地影响了应用逻辑的可测试性。angular为了自动 操作(更新)DOM,提供的数据绑定()。如果我们希望执行我们自定义的DOM操作,可以把表现逻辑抽取到directive( )中。
Input formatting(输入格式化) - 使用angular form controls ()代替。
Output filtering (输出 格式化过滤) - 使用angular filters 代替。
执行无状态或有状态的、controller共享的代码 - 使用angular services 代替。
实例化或者管理其他组件的生命周期(例如创建一个 服务实例)。
四、 Associating Controllers with Angular Scop e Objects
我们可以显式地通过scop e.$new关联controller和scop e对象,或者隐式地通过ngController directive(http://docs.angularjs.org/api/ng.directive:ngController)或者$route service(http://docs.angularjs.org/api/ng.$route)。
1. Controller 构造函数 和方法 的 Example
为了说明controller组件是如何在angular中工作的,让我们使用以下组件创建一个 小应用:
一个 有两个按钮和一个 简单消息的template。
一个 由名为”spice”的字符串属性 组成的model。
一个 有两个设置spice属性 的方法 的controller。
在我们的模版里面的消息,包含一个 到spice model的绑定,默 认设置为”very”。根据被单击按钮,将spice model的值设置为”chili”或者” jalapeño”,消息会被数据绑定自动 更新。
rush:js;">
<
Meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
spicy-controller
<
Meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
The food is {{spice}} spicy!
<script src="../angular-1.0.1.js" type="text/javascript">
<script type="text/javascript">
function SpicyCtrl($scop e) {
$scop e.spice = "very";
$scop e.chiliSpicy = function() {
$scop e.spice = "chili";
};
$scop e.jalapenoSpicy = function(val) {
this.spice = val;
};
}
在上面例子中需要注意的小编:
ngController directive被用作为我们的模版(隐式)创建scop e,那个scop e会称为SpicyCtrl的参数。
SpicyCtrl只是一个 普通的javascript function。作为一个 (随意)的命名规则,名称 以大写字母开头,并以”Ctrl”或者”Controller”结尾。
对属性 赋值可以创建或者更新$scop e的model。
controller方法 可以通过直接分配到$scop e实现创建。(chiliSpicy方法 )
controller的两个方法 在template中都是可用的(在ng-controller属性 所在的元素以及其子元素中都有效)。
注意:之前版本的angular(1.0RC之前)允许我们使用this来代替$scop e定义$scop e的方法 ,但这里不再适用。在定义在scop e上的方法 中,this跟$scop e是等价的(angular将this至为scop e),但不是在我们的controller构造函数 中。
注意:之前版本的angular(1.0RC之前),会自动 增加 controller的prototype方法 到scop e中,但现在不会了。所有方法 都需要人工加入到scop e中。(印象中之前有一个 guide,有用过这个。还没更新-_-!)
controller方法 可以带参数的,正如下面例子所示:
rush:js;">
<
Meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
controller-method-aruments
<
Meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
wasabi"/>
The food is {{spice}} spicy!
<script src="../angular-1.0.1.js" type="text/javascript">
<script type="text/javascript">
function SpicyCtrl($scop e) {
$scop e.spice = "very";
$scop e.spicy = function(spice) {
$scop e.spice = spice;
};
}
注意那个SpicyCtrl controller现在只定义了一个 有一个 参数”spice”、叫”spicy”的方法 。template可以引用controller方法 并为它传递常量字符串或model值。
Controller继承在angular是基于scop e继承的。让我们看看下面的例子:
rush:js;">
<
Meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
controller-inheritance
<
Meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
Good {{timeOfDay}},{{name}}!
Good {{timeOfDay}},{{name}}!
<script src="../angular-1.0.1.js" type="text/javascript">
<script type="text/javascript">
function MainCtrl($scop e) {
$scop e.timeOfDay = 'Main时间';
$scop e.name = 'Main名称 ';
}
function ChildCtrl($scop e) {
$scop e.name = 'Child名称 ';
}
function BabyCtrl($scop e) {
$scop e.timeOfDay = 'Baby时间';
$scop e.name = 'Baby名称 ';
}
注意我们如何嵌套3个ngController directive到模版中的。为了我们的视图,这模版结构将会导致4个scop e被创建:
root scop e。
MainCtrl scop e,包含timeOfDay和name model。
ChildCtrl scop e,覆盖了MainCtrl scop e的name model,继承了timeOfDay model。
BabyCtrl scop e,覆盖了MainCtrl scop e 的timeOfDay以及ChildCtrl scop e的name。
继承的工作,在controller和model中是一样的。所以我们前一个 例子中,所有model可以通过controller被重写。
注意:在两个Controller之间标准原型继承不是如我们所想地那样工作的,因为正如我们之前提到的,controller不是通过angular直接初始化的,但相反地,apply了那个scop e对象。(controllers are not instantiated directly by angular,but rather are applied to the scop e object,这里跟之前一样,我还是没理解。)
五、 Testing Controller
虽然有很多方法 去测试controller,最好的公约之一,如下面所示,需要注入$rootScop e和$controller。(测试需要配合jasmine .js)
rush:js;">
<
Meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
controller-test
<
Meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
mine.css">
<script src="../angular-1.0.1.js" type="text/javascript">
<script src="../angular-scenario-1.0.1.js" type="text/javascript">
<script src="../jas
mine .js" type="text/javascript">
<script src="../jas
mine -html.js" type="text/javascript">
<script src="../angular-mocks-1.0.1.js" type="text/javascript">
<script type="text/javascript">
function MyController($s
cop e) {
$s
cop e.spices = [
{"name":"pasilla","spici
nes s":"mild"},{"name":"jalapeno","spicei
nes s":"hot hot hot!"},{"name":"habanero","spice
nes s":"LAVA HOT!!"}
];
$scop e.spice = "habanero";
}
describe("MyController function",function () {
describe("MyController",function () {
var scop e;
beforeEach(inject(function ($rootScop e,$controller) {
scop e = $rootScop e.$new();
var ctrl = $controller(MyController,{$scop e:scop e});
}));
it('should create "cpices" model with 3 spices',function () {
expect(scop e.spices.length).toBe(3);
});
it('should set the default value of spice',function () {
expect(scop e.spice).toBe("habanero");
});
});
});
(function () {
var jasmine Env = jasmine .getEnv();
jasmine Env.updateInterval = 1000;
var trivialReporter = new jasmine .TrivialReporter();
jasmine Env.addReporter(trivialReporter);
jasmine Env.specFilter = function (spec) {
return trivialReporter.specFilter(spec);
};
var currentwind owOnload = window.onload;
window.onload = function () {
if (currentwind owOnload) {
currentwind owOnload();
}
execJasmine ();
};
function execJasmine () {
jasmine Env.execute();
}
})();
如果我们需要测试嵌套的controller,我们需要在test中创建与DOM里面相同的scop e继承关系。
rush:js;">
<
Meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
controller-test
<
Meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
mine.css">
<script src="../angular-1.0.1.js" type="text/javascript">
<script src="../angular-scenario-1.0.1.js" type="text/javascript">
<script src="../jas
mine .js" type="text/javascript">
<script src="../jas
mine -html.js" type="text/javascript">
<script src="../angular-mocks-1.0.1.js" type="text/javascript">
<script type="text/javascript">
function MainCtrl($s
cop e) {
$s
cop e.timeOfDay = 'Main时间';
$s
cop e.name = 'Main
名称 ';
}
function ChildCtrl($scop e) {
$scop e.name = 'Child名称 ';
}
function BabyCtrl($scop e) {
$scop e.timeOfDay = 'Baby时间';
$scop e.name = 'Baby名称 ';
}
describe("MyController",function () {
var mainScop e,childScop e,babyScop e;
beforeEach(inject(function ($rootScop e,$controller) {
mainScop e = $rootScop e.$new();
var mainCtrl = $controller(MainCtrl,{$scop e:mainScop e});
childScop e = mainScop e.$new();
var childCtrl = $controller(ChildCtrl,{$scop e:childScop e});
babyScop e = childScop e.$new();
var babyCtrl = $controller(BabyCtrl,{$scop e:babyScop e});
}));
it('should have over and selected',function () {
expect(mainScop e.timeOfDay).toBe("Main时间");
expect(mainScop e.name).toBe("Main名称 ");
expect(childScop e.timeOfDay).toBe("Main时间");
expect(childScop e.name).toBe("Child名称 ");
expect(babyScop e.timeOfDay).toBe("Baby时间");
expect(babyScop e.name).toBe("Baby名称 ");
});
});
(function () {
var jasmine Env = jasmine .getEnv();
jasmine Env.updateInterval = 1000;
var trivialReporter = new jasmine .TrivialReporter();
jasmine Env.addReporter(trivialReporter);
jasmine Env.specFilter = function (spec) {
return trivialReporter.specFilter(spec);
};
var currentwind owOnload = window.onload;
window.onload = function () {
if (currentwind owOnload) {
currentwind owOnload();
}
execJasmine ();
};
function execJasmine () {
jasmine Env.execute();
}
})();
以上就是关于 AngularJs Understanding the Controller Component的资料整理,后续继续补充相关资料,谢谢大家的支持 !
原文地址:https://www.jb51.cc/js/46136.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。