【AngularJs學習筆記四】Grunt+Bower+Requirejs+Angular

#0 系列目錄#css

#1 前端開發工具介紹#html

  1. Grunt – Js任務管理工具,經過各類插件對項目進行各類操做,好比文件轉換、運行測試、打包部署等。至關於java裏的ant/maven/gradle,ruby中的rack,scala中的sbt。前端

  2. Bower – Js庫依賴管理工具,當你須要jquery時,不須要手動下載,只須要執行 bower install jquery。java

  3. RequireJs – Js庫加載管理,及模塊化支持,能夠按需及並行加載js庫,能夠把咱們的代碼以模塊化的方式組織。node

  4. AngularJs – Js前端框架,支持依賴注入,雙向綁定等我認爲很重要的功能。jquery

這套東西都是比較基礎且使用比較普遍的。通常一旦在項目中引入前端框架,或者須要寫比較多的Js代碼時,咱們都會採用它們,因此頗有必要學習並掌握它們。git

#2 建立項目目錄# 下面咱們從零開始,首先在任意位置新建一個目錄做爲咱們的項目根目錄,好比:angularjs

mkdir ~/myproject

而後進入該目錄:github

cd ~/myproject

#3 爲npm建立package.json# 首先咱們須要爲npm提供一個 package.json,告訴它咱們的項目信息,特別是項目中將會使用的插件。咱們不須要手動建立,由於能夠直接調用如下命令:npm

npm init

它會問咱們一些問題,咱們能夠按需回答,也能夠所有使用默認值,反正之後能夠改起來也很容易。最後將會產生以下的 package.json 文件:

{
  "name": "myproject",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

對於像咱們這樣的非nodejs項目來講,裏面的大部份內容都沒用,能夠刪掉大部分,只剩下:

{
  "name": "myproject",
  "version": "1.0.0",
}

#4 安裝 grunt#

npm install grunt --save-dev

將使用npm下載grunt插件,它們將保存到項目根目錄下的 node_modules 目錄下。後面的 --save-dev 參數是說,把這個插件信息,同時添加到 package.json 的 devDependencies 中

"devDependencies": {
    "grunt": "^0.4.5"
}

因爲grunt僅在開發階段使用,因此使用 --save-dev 。若是是運行時使用的,則用 --save

#5 安裝 grunt-cli# 上面安裝的 grunt 並不包含命令行工具,咱們還需安裝相應的 grunt-cli ,才能在命令行中調用 grunt 命令:

npm install grunt-cli -g

後面的 -g 是說,把 grunt-cli 安裝成全局工具,以便在任意目錄下使用。安裝後,輸入:

grunt --version

我這裏顯示爲:

grunt-cli v0.1.13
grunt v0.4.5

#6 爲grunt建立配置文件Gruntfile.js#

  1. 安裝grunt-init
npm install grunt-init -g
  1. 下載grunt模板
git clone https://github.com/gruntjs/grunt-init-gruntfile.git ~/.grunt-init/gruntfile
  1. 生成Gruntfile
grunt-init gruntfile

根據須要回答問題,或者使用默認值,將獲得如下 Gruntfile.js 文件:

/*global module:false*/
module.exports = function(grunt) {

    // Project configuration.
    grunt.initConfig({
        // Metadata.
        pkg: grunt.file.readJSON('package.json'),
        banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
                '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
                '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
                '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
                ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
        // Task configuration.
        concat: {
            options: {
                banner: '<%= banner %>',
                stripBanners: true
            },
            dist: {
                src: ['lib/<%= pkg.name %>.js'],
                dest: 'dist/<%= pkg.name %>.js'
            }
        },
        uglify: {
            options: {
                banner: '<%= banner %>'
            },
            dist: {
                src: '<%= concat.dist.dest %>',
                dest: 'dist/<%= pkg.name %>.min.js'
            }
        },
        jshint: {
            options: {
                curly: true,
                eqeqeq: true,
                immed: true,
                latedef: true,
                newcap: true,
                noarg: true,
                sub: true,
                undef: true,
                unused: true,
                boss: true,
                eqnull: true,
                browser: true,
                globals: {
                    jQuery: true
                }
            },
            gruntfile: {
                src: 'Gruntfile.js'
            },
            lib_test: {
                src: ['lib/**/*.js', 'test/**/*.js']
            }
        },
        qunit: {
            files: ['test/**/*.html']
        },
        watch: {
            gruntfile: {
                files: '<%= jshint.gruntfile.src %>',
                tasks: ['jshint:gruntfile']
            },
            lib_test: {
                files: '<%= jshint.lib_test.src %>',
                tasks: ['jshint:lib_test', 'qunit']
            }
        }
    });

     // These plugins provide necessary tasks.
     grunt.loadNpmTasks('grunt-contrib-concat');
     grunt.loadNpmTasks('grunt-contrib-uglify');
     grunt.loadNpmTasks('grunt-contrib-qunit');
     grunt.loadNpmTasks('grunt-contrib-jshint');
     grunt.loadNpmTasks('grunt-contrib-watch');

     // Default task.
     grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']);
};

它裏面已經包含了一些經常使用的插件,好比 grunt-contrib-jshint 等,咱們可根據須要刪減一些用不上的。它同時還會在 package.json 裏添加上這些插件的依賴:

"grunt-contrib-concat": "~0.4.0",
"grunt-contrib-jshint": "~0.10.0",
"grunt-contrib-qunit": "~0.5.2",
"grunt-contrib-uglify": "~0.5.0",
"grunt-contrib-watch": "~0.6.1"

這些插件還未下載,若是須要,能夠運行:

npm install

#7 安裝bower# bower跟npm在某種意義上類似,它是用來管理經常使用的js庫的依賴的,好比jquery, underscore, angularjs等。咱們能夠經過npm安裝它:

npm install bower -g // 把它裝爲全局工具

bower也有它本身的配置文件 bower.json ,咱們不須要手動建立。

bower init

將會生成以下的 bower.json :

{
  "name": "myproject",
  "description": "",
  "main": "",
  "authors": [
    "TaoBangren <mingkai.tao@gmail.com>"
  ],
  "license": "MIT",
  "homepage": "",
  "private": true,
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ]
}

對於咱們的項目來講,裏面的東西基本上都沒用。有用的是後面將會出現的dependencies

#8 下載requirejs、jquery、angularjs#

bower install requirejs --save
bower install jquery --save
bower install angularjs --save

將會自動下載jquery到angularjs相應的文件,到項目根目錄下的 bower_components 目錄。並在 bower.json 中添加:

"dependencies": {
    "requirejs": "~2.1.22",
    "jquery": "~2.2.0",
    "angular": "angularjs#~1.4.9"
  }

#9 安裝grunt-bower-task# bower只負責把依賴下載到本地的 bower_components 目錄,並不負責把它們拷貝到咱們項目中實際使用的地方,好比 public/js/lib 目錄下。爲了實現這樣的功能,咱們還須要另外一個插件的幫助:

npm install grunt-bower-task --save-dev

而後打開其文檔:https://www.npmjs.org/package/grunt-bower-task ,按照上面的提示進行配置。

首先在 Gruntfile 中合適位置添加:

grunt.loadNpmTasks('grunt-bower-task');

而後在 grunt.initConfig({...}) 參數中,添加相應的配置項:

bower: {
    install: {
        options: {
            targetDir: './public/js/lib',
            layout: 'byComponent',
            install: true,
            verbose: false,
            cleanTargetDir: false,
            cleanBowerDir: false,
            bowerOptions: {}
        }
    }
}

這裏指定拷貝的目標目錄爲 public/js/lib ,且文件按照模塊分紅單個目錄(byComponent)。若是想把全部的js放在同一個目錄,全部的css文件放在同一個目錄,則使用 byType

#10 關於RequireJs使用# 在前面咱們已經使用bower安裝了requirejs:

bower install requirejs

RequireJs可用來管理頁面中使用的js庫之間的依賴關係,能夠按需、並行、延遲加載js庫。同時它可讓咱們以模塊化的形式組織js代碼。

前面咱們第三方的依賴,經過grunt-bower-task拷貝到了 public/js/lib 目錄下。咱們本身寫的js,將會放置在 public/js 目錄下。咱們須要手動建立一個 config.js 文件,用來配置和初始化requirejs。

若是咱們使用了requirejs,則在HTML中,咱們一般只須要一個 <script src="..."></script> 標籤引入requirejs並指定入口文件便可,而不須要寫多個 script 標籤手動加載其它js文件。

在HTML中合適位置加入:

<script src="/public/js/lib/requirejs/require.js" data-main="/public/js/config.js"></script>

這裏首先加載了require.js,並經過 data-main 屬性告訴requirejs:當你加載完之後,請加載config.js文件進行初始化。config.js 內容以下:

requirejs.config({
  baseUrl: '/public/js',
  paths: {
    app: 'app',
    jquery: 'lib/jquery/jquery',
    angular: 'lib/angularjs/angular'
  },
  shim: {
  }
});

requirejs(['app'], function(app) {
  app.hello();
});

咱們在 paths 中聲明瞭幾個模塊,其中的 app 是咱們本身建立的js文件,用於放咱們本身的業務代碼,它對應於 /public/js/app.js . jquery 與 angular 對應的文件是咱們使用grunt-bower-task拷貝過來的第三方js庫。

shim 中用來處理一些沒有遵照requirejs規範的js庫,好比 underscore 之類。可在裏面對它們進行一些依賴聲明、初始化操做等。這裏暫時用不上。

最後用 requirejs 來導入咱們本身的模塊,可在後面的callback中拿到對應模塊的實例,並對它進行一些操做,好比咱們調用了 app.hello() 方法。

爲了讓這個例子完整,咱們能夠定義相應的 app.js :

define([], function() {
  return {
    hello: function() {
      alert("hello, requirejs");
    }
  }
});

爲了能讓例子跑起來,咱們還須要建立一個 public/index.html ,內容以下:

<html>
<head>
  <script src="/public/js/lib/requirejs/require.js" data-main="/public/js/config.js"></script>
</head>
<body>
  <div>Hello, world!</div>
</body>
</html>

#11 Angularjs例子# 因爲angularjs並非按requirejs的模塊方式組織代碼的,咱們須要在 config.js 中添加:

shim: {
    angular : { exports : 'angular'}
}

Angularjs會在全局域中添加一個名爲 angular 的變量。咱們必須在 shim 中顯式把它暴露出來,才能經過模塊注入的方式使用它,好比:

define(['angular'], function(ng) {
  // we can use argument `ng` instead of gloabl `angular` now
});

在index.html中添加angular代碼:

<div ng-controller="MyController">
    <input type="text" ng-model="name" />
    <span>{{name}}</span>
</div>

準備相應的controller,把 app.js 的內容改成:

define(['angular'], function(angular) {
    angular.module('myApp', []).controller('MyController', ['$scope', function ($scope) {
        $scope.name = 'Change the name';
    }]);

    angular.element(document).ready(function() {
        angular.bootstrap(document, ['myApp']);
    });
});

在這段代碼裏,我定義了一個angularjs本身的模塊 myApp ,以及相應的 MyController 。在後面,經過 angular.bootstrap 方法,把該模塊與 document 結合在了一塊兒

在html中顯示angularjs裏的一個字段時,咱們使用 {{}} 來佔位,好比:

<span>{{name}}</span>

若是咱們同時使用了mustcahe模板,就會有衝突。咱們能夠更改angularjs的配置:

angular.module('myApp', []).config(function($interpolateProvider){
        $interpolateProvider.startSymbol('[[').endSymbol(']]');
    }
);

而後咱們就能夠寫成:

<span>[[name]]</span>
相關文章
相關標籤/搜索