model

model这个词在AngularJS中,既可以表示一个(比如,一个叫做phonesmodel,它的值是一个包含多个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的实现中,视图是知道模型和控制器的。视图知道模型的双向绑定,视图通过指令知道控制器,比如ngControllerngView指令,也可以通过绑定知道,比如{{someControllerFunction()}}。通过这些方式,视图可以调用相应控制器中的方法。

加油!

AngularJS开发指南11:AngularJS的model,controller,view详解的更多相关文章

  1. [@Controller]3 详解@CookieValue,@PathVariable,@RequestBody,@RequestHeader,@RequestParam

    [@Controller]3 详解@CookieValue,@PathVariable,@RequestBody,@RequestHeader,@RequestParam 转载:http://blog ...

  2. VS 2013驱动开发 + Windbg + VM双机调试(亲测+详解)

    ------------VS 2013驱动开发 + Windbg + VM双机调试(亲测+详解)------------- WIN10已上线,随之而来的是VS2015:微软在 "WDK760 ...

  3. Eclipse进行C/C++开发——Eclipse+CDT+MinGW的配置与使用详解

    http://hi.baidu.com/ltb6w/item/3a51f11926fda60ce75c361d Eclipse进行C/C++开发——Eclipse+CDT+MinGW的配置与使用详解 ...

  4. 【译】ASP.NET MVC 5 教程 - 11:Details 和 Delete 方法详解

    原文:[译]ASP.NET MVC 5 教程 - 11:Details 和 Delete 方法详解 在教程的这一部分,我们将研究一下自动生成的 Details 和Delete 方法. Details ...

  5. AngularJS开发指南16:AngularJS构建大型Web应用详解

    AngularJS是由Google创建的一种JS框架,使用它可以扩展应用程序中的HTML功能,从而在web应用程序中使用HTML声明动态内容.在该团队工作的软件工程师Brian Ford近日撰写了一篇 ...

  6. AngularJS开发指南6:AngularJS表单详解

    表单控件(input, select, textarea )是用来获取用户输入的.表单则是一组有联系的表单控件的集合. 用户能通过表单和表单控件提供验证的服务,知道自己的输入是否合法.这样能让用户交互 ...

  7. AngularJS开发指南1:AngularJS简介

    什么是 AngularJS? AngularJS 是一个为动态WEB应用设计的结构框架.它能让你使用HTML作为模板语言,通过扩展HTML的语法,让你能更清楚.简洁地构建你的应用组件.它的创新点在于, ...

  8. AngularJS开发指南2:AngularJS初始化过程

    自动初始化 请将ng-app指令放到你应用的标签节点中, 如果你想要AngularJS自动执行整个<html>程序就把它放在 <html> 标签中.比如:<html ng ...

  9. SpringMVC【开发Controller】详解

    前言 本文主要是讲解在Controller中的开发,主要的知识点有如下: 编码过滤器 使用注解开发 注解@RequestMapping详解 业务方法接收参数 字符串转日期 重定向和转发 返回JSON ...

随机推荐

  1. 一起学微软Power BI系列-使用技巧(4)Power BI中国版企业环境搭建和帐号问题

    千呼万唤的Power BI中国版终于落地了,相信12月初的微软技术大会之后已经铺天盖地的新闻出现了,不错,Power BI中国版真的来了,但还有些遗憾,国际版的一些重量级服务如power bi emb ...

  2. iOS---iOS10适配iOS当前所有系统的远程推送

    一.iOS推送通知简介 众所周知苹果的推送通知从iOS3开始出现, 每一年都会更新一些新的用法. 譬如iOS7出现的Silent remote notifications(远程静默推送), iOS8出 ...

  3. OpenGL超级宝典笔记----框架搭建

    自从工作后,总是或多或少的会接触到客户端3d图形渲染,正好自己对于3d图形的渲染也很感兴趣,所以最近打算从学习OpenGL的图形API出发,进而了解3d图形的渲染技术.到网上查了一些资料,OpenGL ...

  4. PHP的学习--RSA加密解密

    PHP服务端与客户端交互或者提供开放API时,通常需要对敏感的数据进行加密,这时候rsa非对称加密就能派上用处了. 举个通俗易懂的例子,假设我们再登录一个网站,发送账号和密码,请求被拦截了. 密码没加 ...

  5. SDWebImage源码解读 之 NSData+ImageContentType

    第一篇 前言 从今天开始,我将开启一段源码解读的旅途了.在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划.但能够肯定的是,这一系列之中肯定会有Swift版本的代码. 说说 ...

  6. H5项目开发分享——用Canvas合成文字

    以前曾用Canvas合成.裁剪.图片等<用H5中的Canvas等技术制作海报>.这次用Canvas来画文字. 下图中"老王考到驾照后"这几个字是画在Canvas上的,与 ...

  7. 深入学习jQuery自定义插件

    原文地址:jQuery自定义插件学习 1.定义插件的方法 对象级别的插件扩展,即为jQuery类的实例增加方法, 调用:$(选择器).函数名(参数);      $(‘#id’).myPlugin(o ...

  8. C++ 事件驱动型银行排队模拟

    最近重拾之前半途而废的C++,恰好看到了<C++ 实现银行排队服务模拟>,但是没有实验楼的会员,看不到具体的实现,正好用来作为练习. 模拟的是银行的排队叫号系统,所有顾客以先来后到的顺序在 ...

  9. kvm 使用入门详解

    kvm 是虚拟化技术的一个典型实现,功能非常强大,使用很方便.kvm 本身主要实现对 CPU 的虚拟化,内存和IO的虚拟化使用了开源软件 qemu,qemu 是纯软件层面的虚拟化,其实就是个模拟器.k ...

  10. 机器指令翻译成 JavaScript —— No.3 流程分割

    上一篇 我们讨论了跳转指令,并实现「正跳转」的翻译,但最终困在「负跳转」上.而且,由于线程模型的差异,我们不能 1:1 的翻译,必须对流程进行一些改造. 当初之所以选择翻译,而不是模拟,就是出于性能考 ...