AngularJS:什么时候应该使用Directive、Controller、Service?

AngularJS:什么时候应该使用Directive、Controller、Service?

 

  AngularJS是一款很是强大的前端MVC框架。同时,它也引入了至关多的概念,这些概念咱们可能不是太熟悉。(译者注:老外真谦虚,我大天朝的码农对这些概念那是至关熟悉啊!)这些概念有:Directive(指令)前端

  • Controller(控制器)
  • Service (服务)

 

        下面咱们逐个来看这些概念,研究一下为何它们会像当初设计的那样强大,同时研究一下为何咱们要以那样的方式去使用它们。咱们从Service开始。angularjs

 

 

SERVICES(服务)

 

        若是你已经使用过AngularJS,你可能已经遇到过Service这个概念了,简而言之,Service就是【单例对象】在AngluarJS 中的一个别名。这些小东西(指单例对象)会被常常传来传去,保证你每次访问到的都是同一个实例,这一点和工厂模式不一样。基于这种思想,单例对象让咱们能够 实现一些至关酷的功能,它可让不少controller和directive访问内部的数值。在#angularjs 频道(译者注:指的是原做者本身的博客频道)里面这也是很是常见的问题之一,那就是在应用中的不一样代码块之间如何共享数据?咱们来看这个问题。shell

 

咱们首先来建立一个module(模块),本文中的全部代码都会用到这个module。数组

 

 

var module = angular.module( "my.new.module", [] );

 

       

        下一步,咱们来建立一个新的service(服务)。假设咱们上面的这个module是用来管理图书的。因此,这里咱们来建立一个Book service,而后把一个JSON对象数组添加到这个serice中,这些对象表明不少book数据。app

 

 

module.service( 'Book', [ '$rootScope', function( $rootScope ) {
      var service = {
      books: [
        { title: "Magician", author: "Raymond E. Feist" },
        { title: "The Hobbit", author: "J.R.R Tolkien" }
      ],

      addBook: function ( book ) {
        service.books.push( book );
        $rootScope.$broadcast( 'books.update' );
      }
   }
   return service;
}]);

 

 

        这是一个很是简单的service(有时候这样就够你用了)。咱们这里正在作的事情就是在管理一个book 数组,同时还带有一个addBook方法,在有须要的时候能够添加更多书籍。addBook方法还会在application上广播一个事件,告诉全部正 在使用咱们的service的人,数组已经被更新了,从而让它们本身也作一些刷新操做。如今,咱们要作的就是把这个service传递给各类 controller、directive、filter,或者其它任何须要它的东西---而后它们就能够访问service中的这些方法和属性了。好, 咱们来动手。框架

 

 

var ctrl = [ '$scope', 'Book', function( scope, Book ) {
   scope.$on( 'books.update', function( event ) {
     scope.books = Book.books;
     scope.$apply();//注意,原文这里少了这一行
   }); 
   scope.books = Book.books;
 }];

 module.controller( "books.list", ctrl );

 

 

        一样很是简单。咱们上面所作的就是为咱们的module建立了一个新的controller。在建立的时候把$scope provdier和咱们本身的Book service传递给了它。能明白咱们在干吗吗?咱们把前面建立的Book service中的books数组赋给了controller内部的局部scope对象。很酷,对吧?模块化

 

 

        好,这里的核心问题是什么呢?咱们节省了一些时间,而且在controller上建立了一个数组。对---咱们确实这样作了。这样作确实也为咱们节 约了一点时间---可是若是咱们要在其它地方处理这些书籍信息应该怎么办呢?经过scope来维护数据是很是粗暴的一种方式。因为其它 controller、directive、model的影响,scope很容易就会崩溃或者变脏。它很快就会变成一团乱麻。经过一种集中的途径(在这里 就是service)来管理全部书籍数据,而后经过某种方式来请求修改它,这样不只仅会更加清晰---同时当应用的体积不断增大的时候也更加容易管理。最 后,它还可让你的代码保持模块化(这也是Angular很擅长的一件事情)。一旦你在其它项目中须要用到这个service,你没有必要在scope、 controller、filter等等东西里面处处去查找相关的代码,由于全部东西都在service里面!工具

 

 

        好。那么咱们何时应该使用service呢?答案是:不管什么时候,当咱们须要在不一样的域中共享数据的时候。另外,多亏了Angular的依赖注入系统,实现这一点是很容易而且很清晰的。

单元测试

 

CONTROLLERS(控制器)

 

 

        咱们再来看控制器!除非你曾经使用过前端MVC,不然从服务端MVC的思惟模式转向客户端MVC的思惟模式就如同一次脑筋急转弯。为何会这样呢? 这是由于,虽然在前端开发中controller实现了很是相似的功能,可是它同时还会实现一些与服务端controller很是不一样的功能。在 Angular中,controller自身并不会处理"request",除非它是用来处理路由(route)的(不少人把这种方式叫作建立route controller---路由控制器),更明确地说,尤为是你的应用里面那些做为界面的一部分的controller,它们只会管理很是小的一段代码。测试

 

 

        controller应该纯粹地用来把service、依赖关系、以及其它对象串联到一块儿,而后经过scope把它们关联到view上。若是在你的 视图里面须要处理复杂的业务逻辑,那么把它们放到controller里面也是一个很是不错的选择。回到咱们前面的这个books例子,我实际上并无什 么东西须要添加到controller里面。

 

 

        可是Kirk(译者注:指本文原做者),若是我要add一本书籍应该怎么办呢?我应该在controller上面新增一个方法来处理这件事情吗? 不,缘由在下面解释。由于它是DOM交互/操做的一部分。因此请把它放到directive(指令)里面。怎么作呢?很高兴你能问出这个问题。

 

 

DIRECTIVES(指令)

 

        到目前为止,在咱们所编写的大量AngularJS应用中,应用中最主要的复杂部分都在directive(指令)中。有一个强大的工具能够用来操 做和修改DOM,它也是咱们这里须要讨论的内容。咱们来提供一个按钮,用户经过它能够向service里面添加一本图书,以这一功能来结束此文。

 

 

        一个常见的反模式(按照本人愚见)是在controller里面添加DOM交互代码。Angular对directive的定义是一段代码片断,你 能够用它来操做DOM,可是我以为directive也是进行用户交互的很好选择。咱们来扩展前面的例子,为用户提供一个按钮,经过这个按钮能够向 service里面添加一本书籍。

 

 

module.directive( "addBookButton", [ 'Book', function( Book ) {
    return {
        restrict: "A",
            link: function( scope, element, attrs ) {
            element.bind( "click", function() {
                Book.addBook( { title: "Star Wars", author: "George Lucas" } );
            });
        }
    }
}]);

 

 

        很简单的东西。咱们建立了一个指令,它的核心目的是简单地向books列表中添加一本书籍,books已经注册在了咱们的Book服务中。咱们来把这个指令应用到咱们的视图中。

 

 

<button add-book-button>Add book</button>

 

 

        如你所见,咱们仅仅把指令看成一个元素属性来使用。每次点击这个按钮的时候,它都会把《Star Wars》(《星球大战》)这本书添加到咱们的Book service中去。简单、轻松、模块化---而且易复用。好了,咱们为何不直接在控制器上面添加一个addBook之类的方法呢,好比说就像下面这 样: 

 

$scope.addBook = function() {
     Book.addBook( { title: "Star Wars", author: "George Lucas" } );
 };

 

 

        这样咱们也能得到一样的结果,对吧?是的,确实如此---可是这样作会带来一个重大的问题。一旦我须要在其它地方添加书籍,我必须拷贝这份代码(非 常un-DRY!)(译者注:DRY---Dont Repeat Yourself,貌似是Ruby所倡导的一个重要的编码原则。),或者进行重构(重构自己并非什么很差的的事情)。经过直接构建一个指令的方式,咱们 之后就没有必要担忧这种事情了---同时下次再须要实现相同功能的时候彻底不须要花任什么时候间。经过构建指令的方式来进行DOM交互和修改,随着业务需求的 不断介入,咱们就能够当即腾出手来处理复杂性不断增长的应用了。这是至关不错的一件事情,由于它保证了咱们能够更少地和本身的实现打架,而且能够一直编写 DRYer code。

 

        Angular的模块依赖哲学无疑让它成为了一款非同凡响的框架。它让咱们可以以这样一种方式来编写咱们的前端代码:咱们不会干翻本身,也不会干翻框架---这多是它最强大的力量。

 

 

        但愿我已经充分说明了你应该在什么时候何地使用这几个Angular概念,从而可以更好地编写你本身的代码。

 

 

原文连接:

 

http://kirkbushell.me/when-to-use-directives-controllers-or-services-in-angular/

 


其它相关内容:

 

一、《AngularJS》一书已经由电子工业出版社出版 

http://damoqiongqiu.iteye.com/blog/1965167

 

二、《AngularJS》5个实例详解Directive(指令)机制

 

http://damoqiongqiu.iteye.com/blog/1917971

 

三、AngularJS表单基础

 

http://damoqiongqiu.iteye.com/blog/1920191

 

四、AngularJS Form 进阶:远程校验和自定义输入项

 

http://damoqiongqiu.iteye.com/blog/1920993

 

五、AngularJS:在Windows上安装Yeoman

 

http://damoqiongqiu.iteye.com/blog/1885371

 

六、对比Angular/jQueryUI/Extjs:没有一个框架是万能的

 

http://damoqiongqiu.iteye.com/blog/1922004

 

七、使用JsTestDriver实现JavaScript单元测试

 

http://damoqiongqiu.iteye.com/blog/1924415

 

八、JavaScript单元测试系列二:将Jasmine集成到JsTestDriver

 

http://damoqiongqiu.iteye.com/blog/1925974

相关文章
相关标签/搜索