AngularJS开发指南11:AngularJS的model,controller,view详解
model
model这个词在AngularJS中,既可以表示一个(比如,一个叫做phones的model,它的值是一个包含多个phone的数组)对象,也可以表示应用中的整个数据模型,这取决于我们所讨论的AngularJS文档中的上下文。
在AngularJS中,一个模型就是AngularJS作用域对象中的任何一个可取的属性。属性的名字就是模型的标示符。它的值可以是任意的Javascript对象(包括数组和原始对象)。
将Javascript对象变成模型的唯一要求是这个对象必须是AngularJS作用域的一个属性引用。这个引用既可以显式也可以隐式地创建。
你可以像下面这样显式地创建一个作用域属性,引用Javascript对象:
在Javascript代码中直接将一个对象赋给作用域对象属性;这种情况常见于控制器中:
function MyCtrl($scope) {
// create property 'foo' on the MyCtrl's scope
// and assign it an initial value 'bar'
$scope.foo = 'bar';
}在模板中使用表达式:
<button ng-click="{{foos='ball'}}">Click me</button>在模板中使用
ngInit指令(只适用于实例,不推荐在实际应用中使用):<body ng-init=" foo = 'bar' ">
当处理下面这样的模板结构时,AngularJS会隐式地(通过创建一个作用域对象的属性,并将合适地值赋给它来实现)创建模型。
从input, select, textarea或者其他表单元素中:
<input ng-model="query" value="fluffy cloud">
上面的代码,在当前作用域中创建了一个叫做query的模型,值被设置成"fluffy cloud"。
在
ngRepeater的迭代声明中:<p ng-repeat="phone in phones"></p>
上面代码,为phones数组中的每一项都创建了一个子作用域。并且在各自的作用域中创建了一个叫做phone的对象(模型),它的值被设置成数组中当前的值。
Controller
在AngularJS中,控制器是一个Javascript函数,用来增强除了根作用域以外的作用域实例的。当你或者AngularJS本身通过scope.$new创建一个新的子作用域对象时,有一个选项能让你将它当做参数传递给控制器。这能使AngularjS将控制器和这个作用域联系起来,增强作用域的行为。
控制器用于:
- 设置好作用域对象的初始状态。
- 给作用域对象增加行为。
给作用于对象设置初始状态:
一般来说,当你创建应用时,你需要对它的作用域设置初始状态。
AngularJS将对作用域对象调用控制器的构造函数(从某种意义上来说就像使用Javascript的apply方法一样),以此来设置作用域的初始状态。这意味着AngularJS不会创建控制器类型的实例(不会使用new方法来调用控制器构造函数)。控制器总是对某个已存在的作用域对象调用。
你可以通过创建一个模型属性来设置初始作用域的初始状态。 比如:
function GreetingCtrl($scope) { $scope.greeting = 'Hola!'; }
GreetingCtrl控制器,创建了一个模板中可以调用的,叫greeting的模型。
给作用域对象增加行为
AngularJS作用域对象的行为是由作用域的方法来表示的。这些方法是可以在模板或者说视图中调用的。这些方法和应用的模型交互,并且能改变模型。
如我们在模型那一章所说的,任何对象(或者原生的类型)被赋给作用域后就会变成模型。任何赋给作用域的方法,都能在模板或者说视图中被调用,并且能通过表达式或者ng事件指令调用。(比如,ngClick)
我们如何正确地使用控制器呢?
总的来说,一个控制器不应该做太多工作。它应该只包含单个视图的业务逻辑。
保持控制器职责单一的最常见做法是将那些不属于控制器的工作抽离到服务中,然后通过依赖注入,在控制器中使用这些服务。这在依赖注入服务的章节中会详细讨论。
不要用控制器干下面的事情:
- 控制器应该只关心业务逻辑。DOM操作(表现层逻辑)通常会把测试弄得很难。将任何表现层逻辑放到控制器中都会显著地增加对业务逻辑的测试难度。AngularJS提供
dev_guide.templates.databinding用来自动进行DOM操作。如果你需要手动操作DOM,将表现层的逻辑抽离到指令中。 - 对输入格式化 — 你应该用AngularJS的表单控制来实现格式化。.
- 对输出格式化 — 你应该用AngularJS的过滤器实现。.
- 实例化组件或者控制其它组件的生命周期(比如创建一个服务的实例).
你可以显示地用scope.$new来将控制器和作用域对象显示地联系起来,或者隐式地通过ngController指令或者$route服务来联系。
最后,我们用实例来讲解controller:
为了阐述AngularJS的控制器组件的运行原理,让我们来创建一个拥有下面这些组件的小应用:
- 一个有两个按钮和一条消息的模板
- 一个叫
spice的字符串模型。 - 一个拥有两个方法的控制器SpicyCtrl。这两个方法是用来设置
spice的值。
<body ng-controller="SpicyCtrl">
<button ng-click="chiliSpicy()">Chili</button>
<button ng-click="jalapenoSpicy()">Jalapeño</button>
<p>The food is {{spice}} spicy!</p>
</body> function SpicyCtrl($scope) {
$scope.spice = 'very';
$scope.chiliSpicy = function() {
$scope.spice = 'chili';
}
$scope.jalapenoSpicy = function() {
$scope.spice = 'jalapeño';
}
}
模板中的消息(p元素中的内容)包含了一个对spice模型的绑定,它初始的字符串是“very”。这个spice模型会被设置成 chili 或者 jalapeno,这取决于哪个按钮会被点击。消息会通过数据绑定自动更新。例子中有下面这些需要注意:
ngController指令是用来(隐式地)为模板创建作用域的。并且使用指令中指定的spicyCtrl控制器来增强这个作用域。- 对作用域对象赋予一个新的属性会创建或者更新模型。
- 控制器中的所用方法都能在模板中调用(在body元素或者子元素中).
- AngularJS的老版本(1.0RC之前的)会自动给作用域对象原型添加方法,现在不会了。所有的方法都必须手动添加到作用域。
控制器方法可以接受参数,比如:
<body ng-controller="SpicyCtrl">
<input ng-model="customSpice" value="wasabi">
<button ng-click="spicy('chili')">Chili</button>
<button ng-click="spicy(customSpice)">Custom spice</button>
<p>The food is {{spice}} spicy!</p>
</body> function SpicyCtrl($scope) {
$scope.spice = 'very';
$scope.spicy = function(spice) {
$scope.spice = spice;
}
}
在SpicyCtrl控制器中,只定义了一个叫spicy的方法,它接受一个叫做spice的参数。和这个控制器相关的模板在第一个按钮事件中传递了一个chili常量给控制器中的方法,在第二个按钮中传递一个模型属性。
控制器继承示例:
AngularJS中的控制器继承是基于作用域的继承的,比如:
<body 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>
</body> function MainCtrl($scope) {
$scope.timeOfDay = 'morning';
$scope.name = 'Nikki';
} function ChildCtrl($scope) {
$scope.name = 'Mattie';
} function BabyCtrl($scope) {
$scope.timeOfDay = 'evening';
$scope.name = 'Gingerbreak Baby';
}
注意我们是如何在模板中嵌套我们的ngController指令的。这个模板结构会使得AngularJS为视图创建四个作用域:
- 根作用域
- MainCtrl作用域, 它包含了模型timeOfDay和模型name。
- ChildCtrl作用域,它继承了上层作用域的timeOfDay,复写了name。
- BabyCtrl作用域,复写了MainCtrl中定义的timeOfDay和ChildCtrl中的name。
控制器的继承和模型继承是同一个原理。
注意:常规的原型继承对控制器来说不起作用。因为正如我们之前提到的,控制器不是直接实例化的,而是对作用域对象调用的。
View
在AngularJS中,视图(view)指的是浏览器加载和渲染之后,并且在AngularJS,根据模板、控制器、模型信息修改之后的DOM。
在AngularJS对MVC的实现中,视图是知道模型和控制器的。视图知道模型的双向绑定,视图通过指令知道控制器,比如ngController和ngView指令,也可以通过绑定知道,比如{{someControllerFunction()}}。通过这些方式,视图可以调用相应控制器中的方法。
加油!
AngularJS开发指南11:AngularJS的model,controller,view详解的更多相关文章
- [@Controller]3 详解@CookieValue,@PathVariable,@RequestBody,@RequestHeader,@RequestParam
[@Controller]3 详解@CookieValue,@PathVariable,@RequestBody,@RequestHeader,@RequestParam 转载:http://blog ...
- VS 2013驱动开发 + Windbg + VM双机调试(亲测+详解)
------------VS 2013驱动开发 + Windbg + VM双机调试(亲测+详解)------------- WIN10已上线,随之而来的是VS2015:微软在 "WDK760 ...
- Eclipse进行C/C++开发——Eclipse+CDT+MinGW的配置与使用详解
http://hi.baidu.com/ltb6w/item/3a51f11926fda60ce75c361d Eclipse进行C/C++开发——Eclipse+CDT+MinGW的配置与使用详解 ...
- 【译】ASP.NET MVC 5 教程 - 11:Details 和 Delete 方法详解
原文:[译]ASP.NET MVC 5 教程 - 11:Details 和 Delete 方法详解 在教程的这一部分,我们将研究一下自动生成的 Details 和Delete 方法. Details ...
- AngularJS开发指南16:AngularJS构建大型Web应用详解
AngularJS是由Google创建的一种JS框架,使用它可以扩展应用程序中的HTML功能,从而在web应用程序中使用HTML声明动态内容.在该团队工作的软件工程师Brian Ford近日撰写了一篇 ...
- AngularJS开发指南6:AngularJS表单详解
表单控件(input, select, textarea )是用来获取用户输入的.表单则是一组有联系的表单控件的集合. 用户能通过表单和表单控件提供验证的服务,知道自己的输入是否合法.这样能让用户交互 ...
- AngularJS开发指南1:AngularJS简介
什么是 AngularJS? AngularJS 是一个为动态WEB应用设计的结构框架.它能让你使用HTML作为模板语言,通过扩展HTML的语法,让你能更清楚.简洁地构建你的应用组件.它的创新点在于, ...
- AngularJS开发指南2:AngularJS初始化过程
自动初始化 请将ng-app指令放到你应用的标签节点中, 如果你想要AngularJS自动执行整个<html>程序就把它放在 <html> 标签中.比如:<html ng ...
- SpringMVC【开发Controller】详解
前言 本文主要是讲解在Controller中的开发,主要的知识点有如下: 编码过滤器 使用注解开发 注解@RequestMapping详解 业务方法接收参数 字符串转日期 重定向和转发 返回JSON ...
随机推荐
- C++内存对齐总结
大家都知道,C++空类的内存大小为1字节,为了保证其对象拥有彼此独立的内存地址.非空类的大小与类中非静态成员变量和虚函数表的多少有关. 而值得注意的是,类中非静态成员变量的大小与编译器内存对齐的设置有 ...
- ASP.NET Core 折腾笔记二:自己写个完整的Cache缓存类来支持.NET Core
背景: 1:.NET Core 已经没System.Web,也木有了HttpRuntime.Cache,因此,该空间下Cache也木有了. 2:.NET Core 有新的Memory Cache提供, ...
- .Net 大型分布式基础服务架构横向演变概述
一. 业务背景 构建具备高可用,高扩展性,高性能,能承载高并发,大流量的分布式电子商务平台,支持用户,订单,采购,物流,配送,财务等多个项目的协作,便于后续运营报表,分析,便于运维及监控. 二. 基础 ...
- nodejs模块发布及命令行程序开发
前置技能 npm工具为nodejs提供了一个模块和管理程序模块依赖的机制,当我们希望把模块贡献出去给他人使用时,可以把我们的程序发布到npm提供的公共仓库中,为了方便模块的管理,npm规定要使用一个叫 ...
- Discuz论坛黑链清理教程
本人亲测有效,原创文章哦~~~ 论坛黑链非常的麻烦,如果你的论坛有黑链,那么对不起,百度收录了你的黑链,不会自动删除,需要你手动去清理. 什么是黑链 黑链,顾名思义,就是一些赌博网站的外链,这些黑链相 ...
- 自己实现简单Spring Ioc
IoC则是一种 软件设计模式,简单来说Spring通过工厂+反射来实现IoC. 原理简单说明: 其实就是通过解析xml文件,通过反射创建出我们所需要的bean,再将这些bean挨个放到集合中,然后对外 ...
- TabLayout + ViewPager
一.实现思路 1.在build.gradle中添加依赖,例如: compile 'com.android.support:support-v4:23.4.0'compile 'com.android. ...
- django 学习第一天搭建环境
目前django版本是1.10,我学习的基础教材是 Web Development with Django Cookbook, Second Edition 搭建好配置环境 ssh免认证登录 修改一下 ...
- ORACLE从共享池删除指定SQL的执行计划
Oracle 11g在DBMS_SHARED_POOL包中引入了一个名为PURGE的新存储过程,用于从对象库缓存中刷新特定对象,例如游标,包,序列,触发器等.也就是说可以删除.清理特定SQL的执行计划 ...
- Configure a VLAN (on top of a bond) with NetworkManager (nmcli) in RHEL7
not on top of a bond Environment Red Hat Enterprise Linux 7 NetworkManager Issue Need an 802.1q VLAN ...