1. 程式人生 > >Angularjs開發的一些方法和建議整理

Angularjs開發的一些方法和建議整理

1、如何使用yeoman快速的構建一個Angularjs環境

1.1、安裝node/npm

sudo apt-get install nodejs

*注意:
1 有些時候安裝nodejs後在/usr/bin/只有一個nodejs可執行檔案,但是很多包包括node的指令碼使用的是node,所以需要手動的建立一個node

sudo ln -s /usr/bin/nodejs /usr/bin/node  

2 有些時候安裝源裡面沒有包含npm包,需要獨立安裝

sudo apt-get install npm
tar -xvf node-v*.tar.gz 
./configure
make
sudo make install

1.2、全域性安裝grunt-cli和bower以及yeoman

sudo npm install -g grunt-cli bower yeoman
sudo npm install -g generator-karma generator-angular

1.3、初始化一個angular開發環境

yo angular Test

在這個過程會提示您是否使用sass以及選擇angular相關的組建。
這樣,一個angular開發環境初始化工作就完成了。

2、如何使用angular構建web app

2.1、建議使用的angular組織結構

▾ app/
  ▾ common/
    ▾ dialog/
      ▸ providers/
      ▸ templates/
        dialogModule.js
    ▾ form/
      ▸ directives/
      ▸ styles/
      ▸ templates/
        formModule.js
    ▸ rest/
    ▸ table/
    ▸ toastr/
    ▸ tooltips/
  ▾ container/
    ▾ config/
        router.js
    ▾ controllers/
        containerConsoleController.js
containerController.js containerCreateController.js containerDetailController.js ▸ directives/ ▾ styles/ container.css ▾ templates/ console.html container.html create.html detail.html containerModule.js ▸ home/ ▸ image/ ▸ overview/ ▸ pics/ 404.html favicon.ico index.html
  • 如上所示,common包中包含各個提取出來的通用的angular包,每個包包含自己獨立的module、directives、filters、services、providers、templates、styles等。這樣可以很好的利用angular模組化思想特性,利於抽取common中的包作為多專案的公用包。
  • 除開common包,每一個子app如container、image、overview都是一個獨立的包,同樣包中包含自己獨立的module、config、controllers、directives、filters、services、providers、templates、styles,angular提供的函式注入功能可以很好的實現各個子應用之間的隔離與獨立。

2.2、關於module的使用

module主要定義這個子app的唯一名稱,所依賴的包,如:

angular.module('dockerEasyUiApp',
               ['overview',
                'container',
                'image',
                'rest',
                'table',
                'dialog',
                'form',
                'toastr',
                'tooltip',
                'ngRoute',
                'ngTouch',
                'ngAnimate',
                'ngResource',
                'ngCookies'
]);

2.3、關於config的使用

config一般來說會定義包中一些全域性配置,如路由配置

angular.module('container').config(['$routeProvider', '$locationProvider',
        function indexRouteConfig($routeProvider, $locationProvider) {

    // Disable HTML5 mode (use # for routing)
    $locationProvider.html5Mode(false);

    var APP_NAME = "Docker easy UI";

    // Configure each possible route
    $routeProvider

        //  Container screen
        .when('/container', {
            title         : APP_NAME,
            templateUrl   : 'container/templates/container.html',
            controller    : 'containerController'
        })
        // Image detail screen
        .when('/container/:id', {
            title         : APP_NAME,
            templateUrl   : 'container/templates/detail.html',
            controller    : 'containerDetailController'
        })
        .when('/container/:id/console', {
            title         : APP_NAME,
            templateUrl   : 'container/templates/console.html',
            controller    : 'containerConsoleController'
        })
}]);

如http headers配置

/**
 * The config block for setting up the HTTP method.
 */
angular.module('dockerEasyUiApp').config(['$httpProvider',
        function httpCommonConfig($httpProvider) {

    $httpProvider.defaults.headers.common = {
        'Content-Type': 'application/json'
    }

}]);

2.4、關於services使用

services一般定義的是為controllers服務的方法,如通常web app中的資料來源於伺服器端,需要走http請求,service端可以是對提供http資料請求的封裝,如

angular.module('rest').factory('imageService', ['$injector',
        function imageService($injector) {

    // Required services
    var $http                 = $injector.get('$http');

    // Get required types
    var service = {};

    /**
     * Makes a request to the REST API to get the list of images,
     * returning a promise that provides an array of @link{ImageSample} objects if
     * successful.
     *
     * @param {Object.<Stirng, String>} queryOps
     *     The set of query options to filter with.
     *
     * @returns {Promise.<ImageSample[]>}
     *     A promise which will resolve with an array of @link{ImageSample} objects
     *     upon success.
     */
    service.index = function index(queryOps) {

        // Retrieve Servers
        return $http({
            method  : 'GET',
            url     : '/images/json',
            params  : queryOps
        });

    };

    /**
     * Makes a request to the REST API to get image by id,
     * returning a promise that provides an @link{ImageSample} object if
     * successful.
     *
     * @param {Object.<Stirng, String>} queryOps
     *     The set of query options to filter with.
     *
     * @returns {Promise.<ImageSample>}
     *     A promise which will resolve with an @link{ImageSample} object
     *     upon success.
     */
    service.show = function show(queryOps) {

        // Retrieve Servers
        return $http({
            method  : 'GET',
            url     : '/images/' + queryOps.id + '/json'
        });

    };

    /**
     * Makes a request to the REST API to get image by id,
     * returning a promise that provides an @link{ImageSample} object if
     * successful.
     *
     * @param {Object.<Stirng, String>} queryOps
     *     The set of query options to filter with.
     *
     * @returns {Promise.<ImageSample>}
     *     A promise which will resolve with an @link{ImageSample} object
     *     upon success.
     */
    service.search = function search(searchVal) {

        // Retrieve Servers
        return $http({
            method  : 'GET',
            url     : '/images/search?term=' + searchVal
        });

    };

    /**
     * Makes a request to the REST API to delete a image,
     * returning a promise that provides an Object.<String, String>
     * if successful.
     *
     * @param {String} id
     *     The id of image.
     *
     * @returns {Promise.<Object>}
     *     A promise which will resolve with an object upon success.
     */
    service.del = function del(id) {

        var url = '/images/' + id;

        // Retrieve Servers
        return $http({
            method  : 'DELETE',
            url     : url
        });

    };

    return service;
}]);

Tips:一般在用組建時,為了保持格式的簡潔一致,通暢使用$inject,然後通過$inject.get(“ServiceName”)獲取想要使用的方法。在定義的依賴裡面講所有的依賴都寫出來,顯得比較的臃腫,如

angular.module('test').controller('testController', ['$scope', '$http', '$q', '$timeout', '$router','$location'
        function imageService($scope, $http, $q, $timeout, $router, $location) {
        ....
]);

推薦的優雅的方法是

angular.module('test').controller('testController', ['$scope', '$injecteor'
        function imageService($scope, $injector) {
        var $http     = $injector.get("$http");
        var $q        = $injector.get("$q");
        var $timeout  = $injector.get("$timeout");
        var $router   = $injector.get("$router");
        var $location = $injector.get("$location");
        ....
]);

2.5、關於controller使用

controller被定義為view和data互動的中間樞紐,既然是樞紐,所有controller中更應該體現邏輯,如

angular.module('image').controller('imageController', ['$scope', '$injector',
        function indexController($scope, $injector) {

    // Get image service.
    var imageService = $injector.get("imageService");
    var $dialog      = $injector.get("$dialog");
    var $route       = $injector.get("$route");
    var toastr       = $injector.get("toastr");

    // Define image table columns.
    $scope.imageTableData = {
      checkboxHeader: false,
      singleSelect: true,
      columns: [{
        field: 'isSelected',
        checkbox: true
      }, {
        field: 'Id',
        title: 'ID',
        visible: false
      }, {
        field: 'NamesLink',
        title: 'Repostry Tags',
        align: 'left',
        valign: 'middle',
        sortable: true
      }, {
        field: 'Size',
        title: 'Size',
        align: 'right',
        valign: 'middle',
        sortable: true
      }, {
        field: 'VirtualSize',
        title: 'Virtual Size',
        align: 'right',
        valign: 'middle',
        sortable: true
      }, {
        field: 'ParentId',
        title: 'Parent',
        align: 'left',
        valign: 'middle'
      }, {
        field: 'Created',
        title: 'Created',
        align: 'left',
        valign: 'middle',
        sortable: true
      }],
      data: []
    };
    // Get image list.
    imageService.index({all: 0})
    .success(function(images) {
      angular.forEach(images, function(ele, index) {
        images[index].NamesLink = "<a class='' href='#/image/" +
          images[index].Id + "'>" + images[index].RepoTags + "</a>";
      });
      $scope.imageTableData.data = images;
    });

    // Set image create event.
    $scope.AddImage = function AddImage() {
      $dialog.open({
        templateUrl: 'image/templates/create.html',
        controller: 'imageAddController'
      });
    };

    // Handle image delete action.
    $scope.Del = function Del(mode) {
      if(!$scope.selectedItem) return;
      var selectedItem = $scope.selectedItem;
      //angular.forEach($scope.selectedItems || [], function(ele) {
      imageService.del(selectedItem.Id).success(function (){
        $route.reload();
        toastr.success("Successfully delete image " + selectedItem.RepoTags);
      });
      //});
    }
}]);

如上,controller更著重於呼叫服務,處理view的顯示以及響應view層的事件邏輯。
Tips:一般說來,不太建議在controller中呼叫類似於$(selector).method()這樣的方法,angular一個很重要的思路就是讓開發者從繁雜的dom物件處理中解脫出來!!!但是也有例外,比如處理一些頁面效果時如果使用了jquery外掛,可能需要用到$(selector).method(),但一般這些程式碼體現在directives中。

2.6、關於filters使用

filter第一為處理view顯示的方法,如格式化時間

<div>{{'2012-12-12T12:12:12'|datetime 'YY-MM-DD HH-mm-ss'}}</div>

然後定義一個directive方法處理時間

angular.module('test').filter('datatime', function() {
  return function(text) {
    // handle time formate.
  }
});

Tips:一般說來,不太建議在controller中過多的處理源資料,而是通過定義filter來處理