AngularJS控制器

Controller控制器

控制器的定义

控制器的作用是通过附加模型和和方法来为其扩大作用域,为了随后在视图层能够访问的到。AngularJS中的控制器就是在html文件中AngularJS程序遇到ng-controller指令的时候生成的构造函数。我们将会在下一章中探索AngularJS的作用域。正如我在第一章中提到的,作用域scope就是控制器和视图层之间的胶水,所以控制器能够添加属性,视图层能够访问到这些属性。

为控制器附加属性和方法

下一步,我们写一个控制器,用来通过一个作用域传递现在的时间到视图层。

controller


angular.module('myAPP',[])
.controller('GreetingController',function($scope){
$scope.now=new Data();//把时间模型附加到作用域上
$scope.greeting='Hello';
})

通过在angular.module()上调用controller()来注册一个控制器。这个控制器需要两个参数:第一个参数是这个控制器的名字,第二个是当在html中执行到ng-controller指令时被调用的实例方法。能够忽略这个实例方法中的作用域$scope参数吗?当你声明这个$scope作为一个控制器实例的参数,你就表明你的控制器是依赖于这个$scope对象的。这个$scope的参数有特殊意义。AngularJS根据实例方法参数的名字来推断这个控制器的依赖。在这个例子中,当AngularJS在HTML文件中找到ng-controller='GreetingController'这个指令时,AngularJs会为控制器创建一个新的作用域,当实例化这个方法时,AngularJS会传递这个作用域作为一个参数到这个实例方法。这叫做依赖注入,是AngularJS的核心。我们将会在后面的章节中讨论依赖注入的话题。

多个依赖

能够为控制器设置多个依赖关系,并且能够声明这些依赖作为参数传递到构造方法中。为了增加$scope,每个AngularJS应用都有一个一个$rootScope。我们假设你有一个普通的服务用来通过XHR连接后端。你可以声明这两个服务依赖,像如下一样:


angular.module('myApp',[])
.controller(ControllerWithDependency',function($rootScope,customService){
//在这里使用依赖
});

当实例化控制器的时候,AngularJS会读取参数列表,并且从这些名字中可以指定哪些需要被依赖注入。你也需要注意到AngularJS自己自带的服务前缀是以$为命名约定的。所以你不应该以$作为你服务的前缀。

 


<



{{greeting}} User! The current date/time is {{now | date:'medium'}}


在这里我们把angular的ng-controller指令加入到HTML中,这意味着在标签之间的所有内容均在控制器的作用域下。每次ng-controller检测,AngularJS为这个特殊的控制器和实例创造一个新的作用域。所以当ng-controller="GreetingController"遇到这个构造方法GreetingController运行的时候,为作用域下的两个模型:greeting和now赋值。在视图中我们可以通过表达式{{}}来获取值。当我们写{{greeting}}AngularJS会用这个已经存在greeting属性的值来替代它。对于now模型来说也是如此。无论在{{}}里写的是什么,都要能和scope对应上。

当你在浏览器里运行HTML的时候你应该看到如下

Hello, User! The current date/time is .

添加逻辑到控制器

除了操作用户输入和为控制器赋值,一个控制器也为$scope添加方法,这些方法表现某种类型的逻辑并且和服务一起封装应用的业务数据。
为了明白这些,让我们为$scope添加一个方法,并且在一个随机的语言中返回greeting的值。

下面是如何定义控制器:

angular.module('myApp',[])
  .controller('GreetingController',function($scope){
    $scope.now=new Date();
    $scope.helloMessages = ['Hello', 'Bonjour', 'Hola', 'Ciao',Hallo'];
    $scope.greeting = $scope.helloMessages[0];
    $scope.getRandomHelloMessage=function(){
      $scope.greeting=$scope.helloMessages[parseInt(Math.random()*$scope.helloMessages.length)]
    }
  })

这里我们把helloMessages字符数组数组添加到$scope当前作用域上,表示hello五种语言的表达。我们也为当前作用域$scope上附加了getRandomHelloMessage()方法随机选择一个信息并且赋值给作用域下greeting模型。作为数据绑定的结果,当$scope.greeting被更新,在视图层表达式{{greeting}}也会被改变。

相应的视图是








{{greeting}} User! The current date/time is {{now | date:'medium'}}

这里我们增加了一个HTML按钮用来通过调用在控制器的作用域上getRandomHelloMessage()方法来响应点击事件。反过来,这个方法改变greeting模型的值。所以这个变化被反射到视图层。

诚然,这个例子是很简单的。

但是我们学习到了基本的控制器和如何使用它,现在我们来讨论,控制器不该做什么。

  • 不要进行DOM操作,DOM操作应该在指令中进行。
  • 不要在控制器中格式化模型的值,过滤器的作用就在此,我们已经见过内置过滤器的操作。
  • 不要在控制器中写重复的代码。而是要封装到服务中,例如你要在多个地方从服务中获取数据。所以你与其在控制器中重复代码,不如把代码封装在服务中,当需要的时候注入到控制器中。当所有的控制器线程处理完用户输入后,为当前作用域$scope设置属性和方法,并且和服务进行交互来表现业务逻辑。

    控制器应该做:
    +通过为控制器附加模型来设定$scope的初始状态,
    +为作用域附加方法用来处理任务。

为控制器附加实例方法和属性

尽管控制器经常为作用域设置方法和属性,你也可以为控制器创建一个实例方法和属性。记住,AngularJS实例化你的控制器通过调用你提供的构造方法。这意味着你有创建实例属性和实例方法的自由。让我们定义以前的控制器,用实例属性代替作用域模型。

angular.module('myApp',[])
  .controller('GreetingController',function($scope){
    this.now=new date();
    this.helloMessage=['Hello', 'Bonjour', 'Ola', 'Ciao', 'Hallo'];
    this.greeting = this.helloMessages[0];
    this.getRandomHelloMessage = function() {this.greeting = this.helloMessages[parseInt((Math.random()*this.helloMessages.length))];
  }
})

在视图层有一个小调整。





在AngularJS中使用双向绑定





Two way data binding


  
![](https://graph.facebook.com/{{fbID}}picture?type=normal)

当你看到angularJS的版本的时候会有一点混乱。那这是如何造成的。数据双向绑定的威力刚刚显示出来。我们先来了解场景背后的内容:

1.当我们在input输入的时候,多亏了AngularJS这个fbID模型就会更新。

2.当我们在视图中使用表达式{{fbID}},当fbID模型的值会更新它自己,这样会显示出新图标。

关于angularJS实现最重要的事情是代码的规模是极具下降。甚至实现这个编码功能不使用javascript。这就是声明绑定的能力。你可以通过在视图层通过作用域绑定不同的UI组件来实现一个特殊的场景。如果你的视图层一些需要更新,你需要更新模型层。它确保你表达什么数据被更新了对于一个特殊的组件。如果其他的开发者看到了你的代码,可以推断接下来的应用。

总结一下,双向绑定的特性:

1、在视图层和模型层两个方向,同步的保持数据更新。

2、提供一个强大的陈述性语法来展现应用来实现什么功能。

3、把我们从繁琐的不能测试的DOM操作中解放出来。

4、显著的缩减代码规模。

介绍我们的应用DEMO

学习一个新技术而不练习,这不是忍者的方式。我要确信你每一章节正确的学习方式。练习能够给你在现实世界中操作大型angular项目的信心。所以我们要创建一个示例应用,并且加入一些我们计划的特性。让我们看一看这个简单的示例应用。

一个简单的单页面博客

我们将要为所有的单页面爱好者开发一个单页面应用解决方案。想象一下你有一个高能力的博客系统,由单页面系统控制加载。下面是一个关于这个应用的概括:

(1)博客的首页展现所有的博客帖子,包括帖子的名称、作者和发布时间。

(2)当一个单页面博客被点击的时候,这个实际的条目内容会被异步的加载进这个页面。不会触发整个页面重载。

(3)有一个管理员页面,管理员可以进行增删改查操作。

所以,这是这个app基础的特性。随着我们往前看书,我们将会往app中添加一些激动人心的功能,比如一个完整的评论系统、认证和授权、facebook或者twitter登录界面。

准备开始

刚开始,我们要以在前面章节中讨论过的特征模块化我们的代码。我们已经说过如何把AngularJS。seed项目分解成介绍的这种模式。我们需要做的是从AngularJS seed项目中分解出新项目,并且创造一个简略的不同项目结构。只有这个app下的目录结构需要修改,其他的就不变了。我已经分享过这个目录结构,你可以直接下载后开始。快速的看一下图2.1的屏幕截图,来看看什么改变了。



我已经为这个app增加了一个叫做post的模块,现在还没有添加内容。当你下载完这个zip文件,你可以查看这个文件结构和检查模块。我们将在第五章重新开始开发这个app。

结论

每一个忍者水平的开发者喜欢更强大的能力。现在你得到了三个而不是一个能力,模块、控制器、数据绑定。我想他们会帮助你完成这个angularJS旅程。接下来会带给你一些新的内容。但是同时你可以尝试一些双向绑定的技巧,给你的同事留下印象。

你可能感兴趣的:(AngularJS控制器)