04控制器-AngularJS基础教程

0. 目录

  • 目录
  • 前言
  • 正文
    • 1 ng-controller
    • 2 构建模型-Constructing the model
    • 3 控制器作为属性名-Controller as propertyName
    • 4 依赖注入-Dependency injection
      • 41 scope
    • 5 模型视图控制器MVC-Model-view-controller
    • 6 函数-Functions
    • 7 回调函数
    • 8 结论
  • 声明

1. 前言

AngularJS是为了克服HTML在构建应用上的不足而设计的。HTML是一门很好的为静态文本展示设计的声明式语言,但要构建WEB应用的话它就显得乏力了,所以AngularJS做了一些工作来来解决静态网页技术在构建动态应用上的不足。

AngularJS的初衷是为了简化web APP开发,精髓是简单。但是国内外有很多AngularJS的教程,都着重讲AngularJS的强大之处,从而增加了AngularJS学习的难度,本教程试图用通俗的语言讲解最为基础最为实用的内容,简化学习进程、降低学习难度是本教程的初衷。

本系列教程以翻译Chris SmithAngualr Basics为梗概,融合博主自己的理解,为大家提供一个简单明了的学习教程。

本文为系列教程第4篇控制器,翻译自Controllers

  1. 引言-Introduction
  2. 基础-Basics
  3. 控制器-Controllers
  4. 作用域-Scopes
  5. 集合-Collections
  6. 模块-Modules
  7. 依赖注入-Dependency Injection
  8. 服务-Services
  9. 过滤器-Filters
  10. 指令-Directives
  11. 指令作用域-Directive Scopes
  12. 路由-Routing
  13. 通信-HTTP
  14. 结论

2.正文

在前一章中,我让您勒住缰绳,只把Angular作为HTML的功能扩展,当然Angular远不止这些,事实上通过Javascript实现自定义行为是每个Angular项目的必要部分。如果您在前一章中抱有编程的冲动,你的耐心应该得到嘉奖,现在该写点Javascript了。

最常见的给Angular view(视图)增加控制的方法是通过控制器(controller),最简单的书写控制器的方法是通过书写构造函数的方式。为了帮助大家理解整个过程,我们通过一个非常简单的控制器来演示一下(非常简单,甚至连hello world也没有,就是个空的controller)。

下面是我们的控制器(controller)。

/* empty-controller.js */
function EmptyController() {

};

当然,我们必须把angular类库导入进来,同时利用ng-app命令告诉html,我们将在这里使用angular。

<!-- index.html -->
<!-- 导入类库 -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js"></script>
<!--google被墙,大家可以用国内的cdn-->
<script src="//apps.bdimg.com/libs/angular.js/1.2.16/angular.min.js"></script>
<!-- ng-app告诉html,我们将使用angular -->
<body ng-app="app">
  <!-- Other examples to be inserted here. -->
</body>

控制器可以在全局范围内使用构造函数的方式进行定义,本章就是使用这种方式。在Angular1.3以前版本中可以直接使用简单方式,不过现在需要进行一些配置,创建一个命名的应用模块(named application module)。如何使用Angular模块我们会在接下来的模块、依赖注入和服务章节中详细讲解,现在,你只需要使用下面的案例作为样板文件(boilerplate)即可。

/* module.js */
angular.module(‘app‘, []);
angular.module(‘app‘).config([‘$controllerProvider‘, function($controllerProvider) {
  $controllerProvider.allowGlobals();
}]);

现在我们先不管这些,我们来试试什么都不干的控制器(noop controller)。

2.1 ng-controller

像通常那样,使用指令(directive)可以搞定这些,使用ng-controller指令可以通过它的名字找到并调用控制器函数。

<!-- empty-controller.html -->
<p ng-controller="EmptyController">

</p>

当然,正如您所想,它将调用我们上面定义的那个EmptyController构造函数,nothing to do。接下来,我们来研究下什么是控制器?如何使用?

2.2 构建模型-Constructing the model

在官方指南的核心概览部分把Angular的工作描述为“将变量和函数功能传递给表达式和指令”,这里的函数功能指回调函数,我们稍候重点讲解,现在先来了解一下变量初始化模型准备

明白Angular模型就是表达式作用域可以读取的一些普通Javascript代码之后,准备模型就是小意思了。普通javascript代码?是的,我们可以书写普通js代码,让我们给空的控制器增加一个string属性。

/* message-controller-as.js */
function MessageController() {
  this.message = "This is a model.";
}

简单吧!成功了吗?我们已经成功的创建了一个模型?是也不是?

答案是几乎。当我们在试图作用域中获得message属性之后,它就是一个模型了。完成这个任务的一种方法,就是让整个控制器作为scope中的一个属性,听起来很玄乎吧,当你了解了语法的秘密,一切将变得非常简单。

2.3 控制器作为属性名-Controller as propertyName

正像官方API描述的那样,ng-controller可以接受controll as propertyName表达式作为参数,注意只有Angular1.2以后版本才可使用本特性。

<!-- message-controller.html -->
<p ng-controller="MessageController as controller">
  {{controller.message}}
</p>

编译结果为:This is a model.

这样,我们就是用controller准备好了模型数据。

尽管这种给引用附加属性的方式直接明了,但是“把整个controller暴露给视图”容易给人误解,让人感觉控制器是模型的一部分,而实际上,控制器的作用仅仅是为模型准备数据。当你仅仅满足客户端需求,不考虑更多需求时,测试和调试都会非常简单。而且,这种方式会为视图代码带来噪声,因为所有的属性必须通过控制器的引用访问。视图代码通常是一个web应用噪声要求最苛刻的区域,它可能是一瞥之后出现理解困难的第一个地方。最后,控制器(controller)和作用域(scope)并进工作,从教学角度来说,明晰scope的引用并精细控制它,会非常有用,通过这些控制,我们可以明确地暴露我们想要暴露给视图的部分。因此,本书更倾向于这种能够明确管理scope对象的控制器样式。

那么问题来了,我们如何获得这个scope对象的引用?使用new运算符传建一个?还是从某个地方请求?

2.4 依赖注入-Dependency injection

不是的。我们通过依赖注入获得它。你可能已经注意到我并没有展示实例化控制器的代码,例如var controller=new MessageController();那么,谁创建了视图中使用的控制器?

当然是Angular。Angular是一个控制反转(Inversion of Control,英文缩写为IoC)容器,可以管理应用组件的生存周期。当需要一个新的控制器或者新的组件时,Angular会创建一个。这可以节省时间,而且更重要的是,可以让Angular给组件注入资源、依赖性等。

2.4.1 $scope

作为一个通过依赖注入框架管理的组件,控制器只需要通过一个参数$scope即可。参数的名字非常关键,实际上,如果你压缩了你的Javascript源代码,你会破坏依赖注入机制(无须担心,有一个变通方案,我们会在依赖注入章节详解)。

/* message-controller-scope.js */
function MessageController($scope) {
  $scope.message = "This is a model.";
}

通过给构造函数增加$scope参数,我们通知Angualr我们需要一个视图作用域的引用。可以再简单一些吗?现在我们可以不在控制器里声明message属性,而是直接在scope中定义它。

在模板中,我们从ng-controller指令中移除as controllercontroller.message变成message,这个是我们附加到scope的唯一的属性。

<!-- message-controller-scope.html -->
<p ng-controller="MessageController">
  {{message}}
</p>

编译结果为:This is a model.

尽管两种方式都可以正常工作,本书更多使用指定明确的$scope的方式。依赖注入是Angualr的特色,所以我们要尽可能的熟悉它。

2.5 模型视图控制器MVC-Model-view-controller

官方指南的控制器定义中也涉及到向视图暴露”功能性”。在我们讨论这个问题之前,我觉得有必要花点时间讨论下Angular控制器与经典MVC模式的不同。

根据维基百科model-view-controller (MVC)的解释,控制器“mediates input, converting it to commands for the model or view”。但是很难在Angular范围内理解“commands for the model or view”,因为Angular的MVC模型非常简单,采用仅有规则没有逻辑的贫血模型。截至目前,Angular最流行的方法是,把所有的业务逻辑(域逻辑)放到控制器里,换句话说,Angular应用趋向于瘦模型和胖控制器( skinny models and fat controllers)。

如果您熟悉模式,例如富域模型(rich domain model)、瘦模型胖控制器(Skinny Controller, Fat Model)等,我想你会发现Angular的方法有点倒退。我想这个只可能是优先级问题,在客户端编程中,两者之间存在着显著差异,一边是声明式的、DOM为中心的视图代码,另一边是命令式的、数据驱动的JS代码来处理业务逻辑和应用程序基础。这是巨大的成功,我很高兴类似于Angular之类的框架关注这些。一段时间之后,业务逻辑从控制器中分离开来可能占有更高的优先级,我们可能看到富模型(richer models)的趋势。

2.6 函数-Functions

让我们书写一个包含简单函数的控制器,体验下在视图中调用该函数。你可能会想起,在上一章中我们说过,Angular不允许在视图中声明函数。

下面的控制器把一个函数指定给scope的一个属性。

/* count-controller.js */
function CountController($scope) {
  $scope.count = function() { return 12; }
}

表达式里调用函数方法和普通js代码没有区别,使用{{ }}

<!--count-controller.html-->
<p ng-controller="CountController">
  There are {{count()}} months in a year.
</p>

编译结果为: There are 12 months in a year.

注意,函数不是简单地调用和忘记,而是绑定在模型上。 什么意思? 你Angular的绑定特性(你可能会逐步举得理所当然),意味着Angular不但会在视图第一次渲染时调用该函数,而且会在相关模型改变时调用。为了让大家明白工作原理,我们需要一个使用模型数据的函数,下面的求和函数使用两个scope中声明的模型属性,operand1operand2。Angular将会在任意属性发生改变时调用函数和渲染结果。

/* addition-controller.js */
function AdditionController($scope) {
  $scope.operand1 = 0;
  $scope.operand2 = 0;
  $scope.add = function() {
    return $scope.operand1 + $scope.operand2;
  }
  $scope.options = [0,1,2,3,4];
}

因为我们已经多次使用input指令,这次让我们用Angular的select指令改变模型数据。您可能已经注意到,上面代码的最后一行的$scope.options,我们接下来使用ng-options指令把数组数据放置到select里面。x for x in options这个写法感觉有点废话,无论如何记住它吧()。

<!-- addition-controller.html -->
<p ng-controller="AdditionController">
  <select ng-model="operand1" ng-options="x for x in options"></select>
  + <select ng-model="operand2" ng-options="x for x in options"></select>
  = {{add()}}
</p>

编译之后结果如下面动图所示。

不错吧!但是,如果你不想使用operand1和operand2而想使用属性,我们可以在泛化性上做些改善。摆脱您的重构手册、撸起袖子进行一些参数抽象。

/* addition-controller-params.js */
function AdditionController($scope) {
  $scope.number = 2;
  $scope.add = function(operand1, operand2) {
    return operand1 + operand2;
  }
}

在表达式内部,函数参数可以是属性,也可以是字面值。

<!-- addition-controller-params.html -->
<p ng-controller="AdditionController">
  {{add(number, 2)}} is not the same as {{add(number, "2")}}
  <br>
  2 + 2 + 2 + 2 = {{add(2, add(2, add(2, 2)))}}
</p>

编译结果为:

4 is not the same as 22

2 + 2 + 2 + 2 = 8

接下来,我们通过一个回调函数来处理用户行为。

2.7 回调函数

上一章曾经有一个案例,利用ng-click切换boolean值,在ng-init指令中初始化authorized,利用ng-click="authorized = !authorized实现简单、行内回调,让我们把该案例做个改进,把模型初始化、切换logic变量都放到控制器里去。

/* auth-controller.js */
function AuthController($scope) {
  $scope.authorized = true;
  $scope.toggle = function() {
    $scope.authorized = !$scope.authorized
  };
}

现在toggle是一个作用域中的函数,ng-click的参数看起来像个函数调用toggle()。 它不是真正的函数调用, 只是一个用户单击时会执行的字符串而已。

<!-- auth-controller.html -->
<div ng-controller="AuthController">
  <p>
    The secret code is
    <span ng-show="authorized">0123</span>
    <span ng-hide="authorized">not for you to see</span>
  </p>
  <input class="btn btn-xs btn-default" type="button" value="toggle" ng-click="toggle()">
</div>

编译结果如下动图所示。

案例依然正常工作,而且在一个更好的地方实现了逻辑切换。为什么更好呢?一个很好的问题。在控制器内处理用户行为的好处在于,当我们实现更为复杂的用户行为时可以保证代码清晰可读,例如处理来自远程服务器的异步模型数据(如果您迫不及待的想了解这部分知识,请跳至本书的http部分)。

2.8 结论

我们在Angular的使用中引入了javascript,控制器(controller)在MVC模式中扮演者为视图准备数据的功能,它通过在scope对象上声明属性,实现该功能。下一章中,我们将详细介绍scope对象,了解它如何组织成一个体系与应用的DOM结构匹配。

3.声明

前端开发whqet,关注前端开发,分享相关资源。csdn专家博客,王海庆希望能对您有所帮助,限于作者水平有限,出错难免,欢迎拍砖!

欢迎任何形式的转载,烦请注明装载,保留本段文字。

本文原文链接,http://blog.csdn.net/whqet/article/details/44698845

欢迎大家访问独立博客http://whqet.github.io

时间: 2024-10-15 13:21:08

04控制器-AngularJS基础教程的相关文章

转: angularjs基础教程(~~较通俗)

Angularjs-基础教程(1) 很久没有写过东西了,感觉写东西都不知道从哪里开始了,现在还是先写点技术性的吧,angularjs--我兄弟把它叫成“俺哥啦js” 1.下载 官方网址:https://angularjs.org/ CDN:https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.5/angular.min.js 2.简单介绍使用 1.ng-app   ~~~angularjs的渲染范围 决定了angularjs的作用域

03基础-AngularJS基础教程

0. 目录 目录 前言 正文 1 Set up 2 表达式 3 指令 ng-bind ng-init ng-non-bindable ng-show 4 作用域 双向绑定Two-way binding ng-model 5 总结 声明 1. 前言 AngularJS是为了克服HTML在构建应用上的不足而设计的.HTML是一门很好的为静态文本展示设计的声明式语言,但要构建WEB应用的话它就显得乏力了,所以AngularJS做了一些工作来来解决静态网页技术在构建动态应用上的不足. AngularJS

07模块化-AngularJS基础教程

0. 目录 目录 前言 正文 1 Why use Angular modules为什么使用模块化 2 创建应用模块-Creating the application module 3 加载应用模块-Loading the application module 4 定义控制器-Defining a controller 5 链式定义-Chaining definitions 6 加载模块-Loading modules 10 结论 声明 1. 前言 AngularJS是为了克服HTML在构建应用上

05作用域-AngularJS基础教程

0. 目录 目录 前言 正文 1 setup 2 scope 3 rootScope 4 Isolation隔离 5 Nesting嵌套 6 Inheritance继承 7 scopewatch 8 scopeapply 9 结论 声明 1. 前言 AngularJS是为了克服HTML在构建应用上的不足而设计的.HTML是一门很好的为静态文本展示设计的声明式语言,但要构建WEB应用的话它就显得乏力了,所以AngularJS做了一些工作来来解决静态网页技术在构建动态应用上的不足. AngularJ

06集合-AngularJS基础教程

0. 目录 目录 前言 正文 1 Set up 2 Iteration 3 ng-repeat 4 Object properties 5 index 6 ng-init 7 Uniqueness 71 严格相等 72 track by 8 Callback functions 9 -start and -end 10 结论 声明 1. 前言 AngularJS是为了克服HTML在构建应用上的不足而设计的.HTML是一门很好的为静态文本展示设计的声明式语言,但要构建WEB应用的话它就显得乏力了,

Angular系列----AngularJS入门教程04:迭代器过滤(转载)

我们在上一步做了很多基础性的训练,所以现在我们可以来做一些简单的事情喽.我们要加入全文检索功能(没错,这个真的非常简单!).同时,我们也会写一个端到端测试,因为一个好的端到端测试可以帮上很大忙.它监视着你的应用,并且在发生回归的时候迅速报告. 请重置工作目录: git checkout -f step-3 我们的应用现在有了一个搜索框.注意到页面上的手机列表随着用户在搜索框中的输入而变化. 步骤2和步骤3之间最重要的不同在下面列出.你可以在GitHub里看到完整的差别. 控制器 我们对控制器不做

[转载]AngularJS入门教程04:双向绑定

在这一步你会增加一个让用户控制手机列表显示顺序的特性.动态排序可以这样实现,添加一个新的模型属性,把它和迭代器集成起来,然后让数据绑定完成剩下的事情. 请重置工作目录: git checkout -f step-4 你应该发现除了搜索框之外,你的应用多了一个下来菜单,它可以允许控制电话排列的顺序. 步骤3和步骤4之间最重要的不同在下面列出.你可以在GitHub里看到完整的差别. 模板 app/index.html Search: <input ng-model="query"&g

[分享]Ubuntu12.04安装基础教程(图文)

原文地址: http://teliute.org/linux/Ubsetup/lesson21/lesson21.html 1.进入 live cd 桌面 1)设置好启动后,断开网络,然后重新启动动计算机,能够用硬盘启动,也能够刻成光盘启动,镜像的下载地址: 进入后找蓝色链接点击下载,如 ubuntu-12.04-desktop-i386.iso,64位CPU能够下载amd64的版本号:http://mirrors.sohu.com/ubuntu-releases/12.04/ WinXP硬盘安

Python基础教程(第十章 自带电池)

本文内容全部出自<Python基础教程>第二版,在此分享自己的学习之路. ______欢迎转载:http://www.cnblogs.com/Marlowes/p/5459376.html______ Created on Marlowes 现在已经介绍了Python语言的大部分基础知识.Python语言的核心非常强大,同时还提供了更多值得一试的工具.Python的标准安装中还包括一组模块,称为标准库(standard library).之前已经介绍了一些模块(例如math和cmath,其中包