用Yeoman構建AngularJS項目

轉至https://yq.aliyun.com/articles/25578

Yeoman 介紹

Yeoman 是 Google 的團隊和外部貢獻者團隊合做開發的,他的目標是經過 Grunt(一個用於開發任務自動化的命令行工具)和 Bower(一個HTML、CSS、Javascript 和圖片等前端資源的包管理器)的包裝爲開發者建立一個易用的工做流。javascript

Yeoman 的目的不只是要爲新項目創建工做流,同時仍是爲了解決前端開發所面臨的諸多嚴重問題,例如零散的依賴關係。css

Yeoman 主要有三部分組成:yo(腳手架工具)、grunt(構建工具)、bower(包管理器)。這三個工具是分別獨立開發的,可是須要配合使用,來實現咱們高效的工做流模式。html

  • Yo 搭建新應用的腳手架,編寫你的 Grunt 配置而且安裝你有可能在構建中須要的相關的 Grunt 任務。
  • Grunt 被用來構建,預覽以及測試你的項目,感謝來自那些由 Yeoman 團隊和 runt-contrib 所管理的任務的幫助。
  • Bower 被用來進行依賴管理,因此你再也不須要手動的下載和管理你的腳本了。

下面這幅圖很形象的代表了他們三者之間的協做關係。前端

 

Yeoman 特性:java

  • 快速建立骨架應用程序。使用可自定義的模板(例如:HTML五、Boilerplate、Twitter Bootstrap 等)、AMD(經過 RequireJS)以及其餘工具輕鬆地建立新項目的骨架。
  • 自動編譯 CoffeeScrip 和 Compass。在作出變動的時候,Yeoman 的 LiveReload 監視進程會自動編譯源文件,並刷新瀏覽器,而不須要你手動執行。
  • 自動完善你的腳本。全部腳本都會自動針對 JSHint 運行,從而確保它們遵循語言的最佳實踐。
  • 內建的預覽服務器。你不須要啓動本身的 HTTP 服務器。內建的服務器用一條命令就能夠啓動。
  • 很是棒的圖像優化。使用 OptPNG 和 JPEGTran 對全部圖像作了優化。
  • 生成 AppCache 清單。Yeoman 會爲你生成應用程序緩存的清單,你只須要構建項目就好。
  • 「殺手級」的構建過程。你所作的工做不只被精簡到最少,讓你更加專一,爲你節省大量工做。
  • 集成的包管理。Yeoman 讓你能夠經過命令行輕鬆地查找新的包,安裝並保持更新,而不須要你打開瀏覽器。
  • 對 ES6 模塊語法的支持。你可使用最新的 ECMAScript 6 模塊語法來編寫模塊。這仍是一種實驗性的特性,它會被轉換成 ES5,從而你能夠在全部流行的瀏覽器中使用編寫的代碼。
  • PhantomJS 單元測試。你能夠經過 PhantomJS 輕鬆地運行單元測試。當你建立新的應用程序的時候,它還會爲你自動建立測試內容的骨架。

安裝

安裝前提

一份完整的新手上路指南在這裏能夠找到,可是對於那些但願快速上手操練的傢伙,請肯定你已經安裝了 Node.js, GitRuby 和 Compass 是可選的(若是你想要使用Compass)。node

Node.js 版本要求爲 v0.10.x+,npm 版本要求爲 v2.1.0+,運行下面命令 檢查版本:jquery

$ node --version && npm --version 

也能夠檢查 Git 版本:git

$ git --version 

安裝 Yeoman 工具集

確保 Node 安裝以後,安裝 Yeoman 工具集:angularjs

$ npm install --global yo bower grunt-cli 

運行下面命令檢查是否安裝成功:github

$ yo --version && bower --version && grunt --version 1.4.5 1.3.12 grunt-cli v0.1.13 

安裝 AngularJS 的生成器

Yeoman 生成器使用 npm 命令,如今可用的生成器數量已經超過了 1000+個生成器,這其中不少都是由開源社區編寫的。

你能夠安裝 web 應用的生成器

$ npm install -g generator-webapp 

也能夠安裝 generator-angular 生成器:

$ npm install --global generator-angular 

建立項目

建立一個目錄用於做爲工程目錄:

$ mkdir mytodo && cd mytodo 

你能夠查看全部的生成器:

$ yo ? 'Allo june! What would you like to do? Run a generator Angular Karma Webapp Mocha ────────────── Update your generators (Move up and down to reveal more choices) 

運行 Angular 生成器,會提示你是否使用 Sass 和引入 Bootstrap,以及加載哪些 Angular 模塊:

$ yo angular _-----_ | | .--------------------------. |--(o)--| | Welcome to Yeoman, | `---------´ | ladies and gentlemen! | ( _´U`_ ) '--------------------------' /___A___\ | ~ | __'.___.'__ ´ ` |° ´ Y ` Out of the box I include Bootstrap and some AngularJS recommended modules. ? Would you like to use Sass (with Compass)? No ? Would you like to include Bootstrap? Yes ? Which modules would you like to include? angular-animate.js, angular-cookies.js, angular-resource.js, angular-route.js, angular-sanitize.js, angular-touch.js 

選擇須要下載的模塊,而後回車。過一段時間以後,生成的目錄結構以下:

mytodo ├── Gruntfile.js ├── app │   ├── 404.html │   ├── favicon.ico │   ├── images │   │   └── yeoman.png │   ├── index.html │   ├── robots.txt │   ├── scripts │   │   ├── app.js │   │   └── controllers │   ├── styles │   │   └── main.css │   └── views │   ├── about.html │   └── main.html ├── bower.json ├── bower_components ├── package.json └── test ├── karma.conf.js └── spec └── controllers 

示例中的全部 js 代碼都使用了嚴格模式,有關嚴格模式的內容能夠參考 http://www.waylau.com/javascript-use-strict-mode/

運行下面命令啓動服務:

$ grunt serve 

瀏覽器訪問 ,你會看到:

 

建立 AngularJS 應用

建立新模板展示 Todo 列表

打開 scripts/controllers/main.js ,代碼修改成:

'use strict';

angular.module('webApp').controller('MainCtrl', function ($scope) {
    $scope.todos = ['Item 1', 'Item 2', 'Item 3'];
  });

  

修改 views/main.html,將 todos 中的項目以 input 標籤形式輸出:

<div class="container">
  <h2>My todos</h2>
  <p class="form-group" ng-repeat="todo in todos">
    <input type="text" ng-model="todo" class="form-control">
  </p>
</div>

頁面會顯示以下:

 

 

 

添加一個 todo 項

首先,添加一個輸入框和添加按鈕,將 views/main.html 修改成:

<div class="container">
  <h2>My todos</h2>

  <!-- Todos input -->
  <form role="form" ng-submit="addTodo()">
    <div class="row">
      <div class="input-group">
        <input type="text" ng-model="todo" placeholder="What needs to be done?" class="form-control">
        <span class="input-group-btn">
          <input type="submit" class="btn btn-primary" value="Add">
        </span>
      </div>
    </div>
  </form>
  <p></p>

  <!-- Todos list -->
  <p class="form-group" ng-repeat="todo in todos">
    <input type="text" ng-model="todo" class="form-control">
  </p>
</div>

  

這時候,頁面內容以下:

修改 main.js 添加 addTodo() 事件:

'use strict';

angular.module('webApp')
  .controller('MainCtrl', function ($scope) {
    $scope.todos = ['Item 1', 'Item 2', 'Item 3'];
    $scope.addTodo = function () {
      $scope.todos.push($scope.todo);
      $scope.todo = '';
    };
  });

  

這樣,就完成了添加 todo 項的功能。

移除一個 todo 項目

先在列表中每個 todo 項目的邊上加上一個移除按鈕,修改 views/main.html 中 Todos list 註釋部分的代碼爲:

<!-- Todos list -->
<p class="input-group" ng-repeat="todo in todos">
  <input type="text" ng-model="todo" class="form-control">
  <span class="input-group-btn">
    <button class="btn btn-danger" ng-click="removeTodo($index)" aria-label="Remove">X</button>
  </span>
</p>

  

修改 main.js 添加 removeTodo($index) 事件:

'use strict';

angular.module('webApp')
  .controller('MainCtrl', function ($scope) {
    $scope.todos = ['Item 1', 'Item 2', 'Item 3'];
    $scope.addTodo = function () {
      $scope.todos.push($scope.todo);
      $scope.todo = '';
    };

    $scope.removeTodo = function (index) {
      $scope.todos.splice(index, 1);
    };
  });

  

如今,刪除按鈕可以響應刪除事件了。雖然咱們能夠添加和移除 Todo 事項,可是這些記錄都不能永久地保存。一旦頁面被刷新了,更改的記錄都會不見了,又恢復到 main.js 中設置的todo 數組的值。

另外,上面添加 Todo 項時,若是重複添加相同的記錄,則後臺會報錯,這是由於腳本中沒有作校驗。

對 Todo 事項進行排序

接下來,咱們安裝並引入 AngularUI Sortable 模塊,使得 Todo 事項能夠排序。這裏,咱們須要使用 bower 安裝 angular-ui-sortable 和 jquery-ui:

$ bower install --save angular-ui-sortable jquery-ui 

添加參數 --save 能夠更新 bower.json 文件中關於 angular-ui-sortable 和 jquery-ui 的依賴,這樣你就不用手動去 bower.json 中更新依賴了。

再次啓動 grunt server:

$ grunt serve 

爲了使用Sortable模塊,咱們須要在 scripts/app.js 中更新Angular 模塊,將 Sortable 能夠加載到咱們的應用中,更改前代碼, 將 ui.sortable 添加進數組中,以下:

angular.module('webApp', [ 'ngAnimate', 'ngCookies', 'ngResource', 'ngRoute', 'ngSanitize', 'ngTouch', 'ui.sortable' ]) 

最後,在 views/main.html 中,咱們須要將 ui-sortable 指令做爲一個 div 將 ng-repeat 層包起來。

<!-- Todos list --> <div ui-sortable ng-model="todos"> <p class="input-group" ng-repeat="todo in todos"> 

添加一些內聯的 CSS,將鼠標顯示爲 「可移動」 樣式來告訴用戶這些 todo 項是能夠移動的:

<p class="input-group" ng-repeat="todo in todos" style="padding:5px 10px; cursor: move;"> 

完整代碼以下:

<!-- Todos list --> <div ui-sortable ng-model="todos"> <p class="input-group" ng-repeat="todo in todos" style="padding:5px 10px; cursor: move;"> <input type="text" ng-model="todo" class="form-control"> <span class="input-group-btn"> <button class="btn btn-danger" ng-click="removeTodo($index)" aria-label="Remove">X</button> </span> </p> </div> 

服務瀏覽器,咱們就能夠對 Todo 事項進行拖拽排序了。

持久化存儲

以前項目的數據,當瀏覽器刷新後就不會保存了。咱們能夠安裝 Angular 模塊 angular-local-storage,快速實現本地存儲。

下載依賴:

$ bower install --save angular-local-storage 

編輯 scripts/app.js 添加 LocalStorageModule的 適配器:

angular .module('webApp', [ 'ngAnimate', 'ngCookies', 'ngResource', 'ngRoute', 'ngSanitize', 'ngTouch', 'ui.sortable', 'LocalStorageModule' ]) 

同時也要配置 localStorageServiceProvider,用 ls 做爲 localStorage名稱前綴:

.config(['localStorageServiceProvider', function(localStorageServiceProvider){ localStorageServiceProvider.setPrefix('ls'); }]) 

完整的 scripts/app.js 文件:

'use strict';

angular
  .module('webApp', [
    'ngAnimate',
    'ngCookies',
    'ngResource',
    'ngRoute',
    'ngSanitize',
    'ngTouch',
    'ui.sortable',
    'LocalStorageModule'
  ]).config(['localStorageServiceProvider', function(localStorageServiceProvider){
    localStorageServiceProvider.setPrefix('ls');
  }]).config(function ($routeProvider) {
    $routeProvider
      .when('/', {
        templateUrl: 'views/main.html',
        controller: 'MainCtrl'
      })
      .when('/about', {
        templateUrl: 'views/about.html',
        controller: 'AboutCtrl'
      })
      .otherwise({
        redirectTo: '/'
      });
  });

  

而後,須要修改 scripts/controllers/main.js ,改成從本地存儲訪問數據:

'use strict';

angular.module('webApp').controller('MainCtrl', function ($scope, localStorageService) {

    // 初始化時爲空
    var todosInStore = localStorageService.get('todos');

    $scope.todos = todosInStore && todosInStore.split('\n') || [];

    // 監聽變化
    $scope.$watch('todos', function () {
      localStorageService.add('todos', $scope.todos.join('\n'));
    }, true);

    $scope.addTodo = function () {
      $scope.todos.push($scope.todo);
      $scope.todo = '';
    };

    $scope.removeTodo = function (index) {
      $scope.todos.splice(index, 1);
    };

  });

  

在瀏覽器中查看應用,你會發現 todo 列表中沒有任何東西。由於這個應用從本地存儲中讀取了 todo 數組,而本地存儲中尚未任何 todo 項。

在添加一些項目到列表後,咱們再次刷新咱們的瀏覽器的時候,這些項目都還在。

測試

Karma 是一個 JS 測試框架。Angular 生成器自己已經包括了兩個測試框架:ngScenario 和 Jasmine。當以前咱們運行 yo angular 的時候,在 mytodo 文件夾下會生成了一個 test 目錄,還有一個 karma.conf.js 文件,它會被放入在 Node 模塊中以使用 Karma。咱們將會編輯一個 Jasmine 腳原本完成咱們的測試。如今先來看看要怎麼進行測試。

先安裝依賴:

$ npm install -g phantomjs $ npm install grunt-karma --save-dev 

更新 Karma 配置

首先,修改 karma.conf.js,添加

'bower_components/jquery/dist/jquery.js', 'bower_components/jquery-ui/ui/jquery-ui.js', 'bower_components/angular-ui-sortable/sortable.js', 

最終的樣子是:

files: [
  'bower_components/angular/angular.js',
  'bower_components/angular-mocks/angular-mocks.js',
  'bower_components/angular-animate/angular-animate.js',
  'bower_components/angular-cookies/angular-cookies.js',
  'bower_components/angular-resource/angular-resource.js',
  'bower_components/angular-route/angular-route.js',
  'bower_components/angular-sanitize/angular-sanitize.js',
  'bower_components/angular-touch/angular-touch.js',
  'bower_components/jquery/dist/jquery.js',
  'bower_components/jquery-ui/ui/jquery-ui.js',
  'bower_components/angular-ui-sortable/sortable.js',
  'app/scripts/**/*.js',
  'test/mock/**/*.js',
  'test/spec/**/*.js'
],

  

運行測試

如今回到命令行結束 grunt server 的進程(使用 Ctrl+c)。在 Gruntfile.js 中已經有了用於運行測試的 grunt 任務,能夠直接像下面這樣運行:

$ grunt test 

添加更多測試

修改 test/spec/controllers/main.js 以下:

'use strict';

describe('Controller: MainCtrl', function () {

  // load the controller's module
  beforeEach(module('webApp'));

  var MainCtrl,
    scope;

  // Initialize the controller and a mock scope
  beforeEach(inject(function ($controller, $rootScope) {
    scope = $rootScope.$new();
    MainCtrl = $controller('MainCtrl', {
      $scope: scope
    });
  }));

  it('should attach a list of awesomeThings to the scope', function () {
    expect(scope.awesomeThings.length).toBe(3);
  });

  it('should add items to the list', function () {
    scope.todo = 'Test 1';
    scope.addTodo();
    expect(scope.todos.length).toBe(4);
  });

  it('should add then remove an item from the list', function () {
    scope.todo = 'Test 1';
    scope.addTodo();
    scope.removeTodo(0);
    expect(scope.todos.length).toBe(2);
  });
});

  

更多有關單元測試的內容,請參考 Unit Testing Best Practices in AngularJS

發佈應用

爲了將應用發佈爲產品版本,還須要作不少工做:

  • 校驗咱們的代碼
  • 運行咱們的測試
  • 合併和縮小腳本和樣式來減小網絡請求
  • 優化任何使用到的圖像
  • 對全部輸出進行編譯處理,使程序瘦身

實現上述目標只需一句:

$ grunt 

這個命令將會完成 Grunt 的任務以及根據 Gruntfile.js 文件進行配置,建立一個能夠運行的應用版本。只需等上一分鐘,你就能獲得一個完整的編譯版本,和一份編譯過程耗時的報告。

編譯完成後的文件,放在了 dist 目錄下,是一個能夠拿去服務器上的部署的真正的產品。

你也能夠運行下面命令自動編譯項目,而且啓動 web 服務器

$ grunt serve:dist 

總結

Anugular 生成器也支持建立新的視圖、指令和控制器。例如:能夠經過運行 yo angular:route routeName 搭建一個新的控制器,同時在 app.js 中的路由也會被更新。

瞭解更多有關於 Angular 生成器的 Yeoman 命令,請查看 generator readme

固然,Yeoman 還能夠作更多的事情,它還支持其餘框架的腳手架。

除了 Yeoman 以外,還有幾個框架能夠生產 Angular 項目,請參考 5 Angular JS Seeds & Bootstrap Apps

相關文章
相關標籤/搜索