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

04控制器-AngularJS基础教程相关推荐

  1. AngularJs 基础教程 —— 控制器

    为什么80%的码农都做不了架构师?>>>    本文为 H5EDU 机构官方 HTML5培训 教程,主要介绍:AngularJs 基础教程 -- 控制器 AngularJS 控制器A ...

  2. AngularJs 基础教程 —— 依赖注入

    为什么80%的码农都做不了架构师?>>>    本文为 H5EDU 机构官方 HTML5培训 教程,主要介绍:AngularJs 基础教程 -- 依赖注入 AngularJS 依赖注 ...

  3. AngularJs 基础教程​ —— Select(选择框)

    为什么80%的码农都做不了架构师?>>>    本文为 H5EDU 机构官方 HTML5培训 教程,主要介绍:AngularJs 基础教程 -- Select(选择框) Angula ...

  4. 02引言-AngularJS基础教程

    0. 目录 目录 前言 正文 1 AngularJS 难或易 2 您需要Angular吗 3 使用Angular的理由 4 关于本书 5 接下来 声明 1. 前言 AngularJS是为了克服HTML ...

  5. AngularJs基础视频教程 大漠穷秋AngularJs基础教程 AngularJs入门教程

    1-1:课程简介.mp4 1-2:快速上手.mp4 1-3:开发.调试.测试工具(1).mp4 1-4:开发.调试.测试工具(2).mp4 1-5:开发.调试.测试工具(3).mp4 1-6:开发.调 ...

  6. 3元特卖好课AngularJs基础视频教程 大漠穷秋AngularJs基础教程 AngularJs入门教程

    1-1:课程简介.mp4 1-2:快速上手.mp4 1-3:开发.调试.测试工具(1).mp4 1-4:开发.调试.测试工具(2).mp4 1-5:开发.调试.测试工具(3).mp4 1-6:开发.调 ...

  7. Linux(Ubuntu 20.04 LTS)之shell使用基础教程

    Linux(Ubuntu 20.04 LTS)之shell使用基础教程 我在此使用的是VMware虚拟机安装的Ubuntu 20.04 LTS. Shell是linux系统的用户界面.Shell即是一 ...

  8. ArcGIS二次开发基础教程(04):有关字段的操作和简单属性及空间查询

    ArcGIS二次开发基础教程(04):有关字段的操作和简单属性及空间查询 属性 字段的添加.删除和查找 IFeatureLayer GetLayerByName(string name) {ILaye ...

  9. Laravel 5 基础教程 || 2.路由:链接与控制器的连接者 - 表严肃

    Laravel 5 基础教程 || 2.路由:链接与控制器的连接者 - 表严肃 教程目录 1.安装与部署 - 表严肃 2.路由:链接与控制器的连接者 - 表严肃 3.控制器:任务的分发者 - 表严肃 ...

最新文章

  1. 上海市提出IDC建设指导意见,新建IDC限制PUE1.3以下
  2. Numpy-浅拷贝和深拷贝
  3. 全程图解交换机和路由器的应用
  4. 洛谷P3296 刺客信条
  5. J2EE开发技术点4:ajax技术
  6. 《AutoCAD 2016中文版从入门到精通》——1.5 基本输入操作
  7. 苹果修复被 XCSSET 恶意软件滥用的3个 0day
  8. Spring.NET学习笔记8——集合类型的注入(基础篇) Level 200
  9. 读Zepto源码之Touch模块
  10. vscode ctrl + s自动保存代码 插件安装
  11. 如何快速爬取网页数据(干货)
  12. 程序员必备算法——排列组合
  13. 食疗肠易激综合征 心脏神经官能症
  14. linux 函数中打印调用栈
  15. idea很带劲的插件
  16. 学生论坛管理系统的设计与实现
  17. css nth-child_比较CSS伪类:nth-​​child与nth-of-type
  18. win7 64bit共享XP M1005打印机
  19. Linux启动过程学习
  20. 堕落之后重新开始学习

热门文章

  1. pkcs1转pkcs8 php,pkcs1与pkcs8格式RSA私钥互相转换
  2. 获取微信小程序页面路径的方法
  3. Win10连接打印机提示0x00004005错误的解决教程
  4. 一款js生成的不错的页面上雪花飞舞效果
  5. 面试官:如何在 Docker 容器中抓包?问倒一大片。。。。
  6. 哈尔滨市科学技术局领导莅临开源网安参观交流
  7. SQL Server 性能调优(内存)
  8. Idea git切换远程分支
  9. 基于AHB Slave设计及验证平台搭建
  10. 三菱FX3U——ST的创建工程、新建数据