一步一步構(gòu)建Angular應(yīng)用 Vol.1

序言

目的

這將是一個系列文灸拍,動機是為了希望給公司及項目組其他的新人同學同事作為入門教材使用做祝。
整個系列將從零開始構(gòu)建一個基于完整工具鏈構(gòu)建的angular應(yīng)用。使用的工具包括且不僅限于:

  • nodejs/npm
  • gulp
  • sass/scss

我們將完成什么

我們使用Angular做一個很簡單的鸡岗,包括登陸與一些基礎(chǔ)增刪改查的應(yīng)用混槐。

Vol.1 使用npm,bower,gulp構(gòu)建最基本的angular開發(fā)環(huán)境

介紹

本文面向有一定基礎(chǔ)的Angular開發(fā)者,如果您是第一次接觸angular轩性,我建議您先去看下大漠窮秋先生寫的基礎(chǔ)教程書籍或者通過使用yoeman進行構(gòu)建声登,對angular的工程化編寫有一個初步的認識。

本次使用的組件與相應(yīng)演示代碼

使用npm與bower進行第三方組件包的管理

什么是npm


npm是nodejs提供的包管理工具(package management),對于js應(yīng)用的開發(fā)類似于java的mvn,ruby的gem揣苏。用于管理應(yīng)用相關(guān)的第三方組件與工具悯嗓,而不是“上古”時期,開發(fā)人自己下載解壓縮放到指定目錄卸察,再通過<script>標簽進行引入脯厨。
比如最常見的我們引入jquery,我們除了引入了文件還需要進行版本的控制。

<script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>

而使用npm進行管理則是通過描述文件進行相關(guān)的版本控制管理坑质,將第三方組件管理排除與應(yīng)用代碼之外合武,為工程化管理代碼提供便利。
除此以外npm還提供了許多nodejs周邊cli工具的包管理涡扼,比如nodejs自己本身稼跳。

什么是bower

bower主頁圖

bower是由twitter開發(fā)的一套客戶端包管理工具。其思想與npm基本是一致的吃沪,為什么會有兩套不同的管理體系一直是一個懸而未解的謎團汤善。
通常來說客戶端的包依賴我們會通過bower進行管理,而服務(wù)端(如果存在)則會使用npm進行管理依賴。
因為客戶端的包大部分都是js形式的第三方組件包红淡,而npm包又不少是需要進行本地編譯的cli工具包卸伞。
不過最近已經(jīng)開始有開始提倡所有第三方包依賴都通過npm進行管理的趨勢了。

那么什么是gulp

gulp主頁圖

gulp是js的又一種比較流行的锉屈、基于任務(wù)的構(gòu)建工具。類似C語言的make垮耳,Java的ant颈渊、maven,Ruby的rake终佛。
而gulp的插件機制又提供給了開發(fā)者許多遍歷俊嗽,使js存在一個“編譯期“的概念。
這部分我們先不展開铃彰。

初始化npm和bower

開始前請確定您已經(jīng)安裝了最新版本的nodejs,我使用的版本是mac的v4.2.1
我們先全局安裝一下bower

 npm install -g bower

完成后,我們新建工程文件夾绍豁,并且命名為news。
其次我們依次輸入初始化命令:

npm init
bower init

之后我們并會得到兩個文件,package.json與bower.json,兩個文件分別用于描述我們依賴的第三方包清單牙捉。

通過npm安裝gulp

與安裝bower一樣竹揍,我們需要安裝一下gulp,但有所區(qū)別的是,我們希望將來所有使用我們這份代碼的人都會可以通過npm自動安裝下gulp邪铲。則我們需要比剛才的命令多打一個后綴參數(shù):

 npm install gulp --save-dev //npm下載后會將相關(guān)組件信息記錄與package.json

鍵入完命令后芬位,npm會做兩件事情:

  1. 下載gulp的最新版本至node_modules文件夾下
  2. 將gulp的組件記錄插入至package.json
    我們查看下最新的package.json其內(nèi)容將會出現(xiàn)gulp的信息。
  "devDependencies": {
    "gulp": "^3.9.1"
  }

通過bower下載angualrjs

與npm安裝gulp一樣,我們通過bower的cli命令來安裝angular

bower install angular --save 
  1. bower會下載angular最新版本至bower_components文件夾下带到,
  2. 相關(guān)信息記錄與bower.json中
\\bower.json會出現(xiàn)angular信息
  "dependencies": {
    "angular": "^1.5.4"
  }

至此昧碉,相當文件夾下的目錄結(jié)構(gòu)便是

-news
  --node_modules
  --bower_components
  -package.json
  -bower.json

進入angular環(huán)節(jié)

這次我們就會比較簡單的做一個只有一頁的angualr應(yīng)用,我們首先在news目錄下新建一個app目錄用于存儲所有我們自行編寫應(yīng)用代碼揽惹。其目錄結(jié)構(gòu)為

-news
  --app
    --scripts  //所有js代碼
    --styles  //所有樣式代碼
    -home.html //頁面
    -index.hmtl //入口頁面

第一個應(yīng)用

這次我們目的是做一個歡迎的頁面被饿,其訪問的url為/home,用戶在下面輸入自己姓名的后搪搏,上面的歡迎信息會自動發(fā)生變化的小應(yīng)用狭握。

安裝angular-ui-router

angular-ui-router是angular中一套比較常用的路由控制庫。什么是路由控制呢慕嚷?也就是把url當成狀態(tài)入口與相關(guān)控制器哥牍、視圖進行分發(fā)綁定的組件。
我們通過bower進行安裝,

 bower install angular-ui-router --save

編寫我們的入口index.html

我們的目的是編寫一個spa(單頁應(yīng)用)喝检,則index.html則負責在第一次的時候為用戶訪問整個系統(tǒng)提供入口嗅辣,下載相關(guān)的依賴資源。

\\index.html
<!doctype html>
<html ng-app="app" >  
  <head>
    <meta charset="utf-8">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width">
  </head>
  <body >
    <div ui-view>

    </div>
    <!-- 將bower下載關(guān)聯(lián)的組件js引入-->
    <script src="bower_components/angular/angular.js"></script>
    <script src="bower_components/angular-ui-router/release/angular-ui-router.js"></script>
    </body>
</html>

如何開發(fā)運行應(yīng)用呢挠说?

如果之前沒有接觸過web開發(fā)和nodejs的同學在這里多半會將整個工程放到apache的htdoc目錄下進行訪問測試了吧澡谭?
而知道http-server的同學在news目錄下運行了http-server又發(fā)現(xiàn),上文中的script引入bower組件的地址是不正確的,并且地址欄上多一個app的目錄路徑蛙奖。
推薦的做法是使用gulp-connect來管理開發(fā)環(huán)境的服務(wù)器啟動潘酗。

通過npm安裝gulp-connect

我們一樣通過npm來裝gulp-connect組件

 npm install gulp-connect --save-dev

然后我們新建一個gulpfile.js文件來定義開發(fā)服務(wù)器的啟動任務(wù):

\\gulpfile.js
'user strict';

var gulp = require('gulp');   //require node_modules中的gulp包
var path = require("path"); 
var connect = require("gulp-connect"); //require node_modules中的gulp-connect包

var ROOT_PATH = path.resolve(__dirname); //項目根目錄
var APP_PATH = path.resolve(ROOT_PATH,"app"); //應(yīng)用代碼目錄

gulp.task("connect",function(){
    connect.server({
        root: ["app"],   //使用哪個目錄作為啟動的根目錄
        livereload:true,  //實施加載,可理解為熱部署
        middleware: function(connect) {
              return [connect().use('/bower_components', connect.static('bower_components'))];  //見下文
          }
    });
});

gulp.task("default",["connect"]);  // gulp如缺省目標task則使用connect作為task

我們通過在gulp中新建了一個connect任務(wù)雁仲,使用connect.server來啟動一個開發(fā)部署的http服務(wù)器進行開發(fā)仔夺,其中root,livereload參數(shù)都不難理解。那么middleware的目的是什么呢攒砖?
這里要再次拿我們代碼目錄拿出來說一下缸兔,現(xiàn)在我們的代碼目錄應(yīng)該是這樣的

-news
  --node_modules
  --bower_components
  -package.json
  -bower.json
  --app   <---http啟動加載的文件根目錄
    --scripts
    --styles
    -index.html
    -home.html

則當服務(wù)器啟動后index.html,我們是無法訪問到在http目錄以外的bower_compments目錄中的第三方組件包的吹艇。我們做middelware的動機就是讓connect額外的將/bower_compmenets文件夾加載到我們的應(yīng)用服務(wù)器的內(nèi)容中惰蜜,就好比我們復(fù)制了一個備份到/app/bower_compmenets文件夾中。
當我們現(xiàn)在在應(yīng)用目錄下鍵入gulp命令后受神,便可看到控制端有以下的提示信息

服務(wù)器啟動啦

我們便可在瀏覽器輸入地址127.0.0.1:8080訪問到我們index.html文件抛猖,并且也可以正確的引入相關(guān)的angular組件。

編寫Module

可能很多同學想到是先去寫一個controller來實現(xiàn)我們預(yù)期的功能鼻听,但我們提倡的是around module的開發(fā)模式财著,即所有的controller,service等angular組件全部圍繞著module進行組織。故我們這里先將全局的module編寫精算。

\\  app/scripts/index.module.js

(function ()
{
    'use strict';

    angular
        .module('app', [
            'ui.router'   
        ])
        .config(routeConfig);

    routeConfig.$inject = ['$stateProvider', '$urlRouterProvider','$locationProvider'];  
    function routeConfig($stateProvider, $urlRouterProvider, $locationProvider)
    {

        $stateProvider
                .state('home', {
                    url: '/home',
                    templateUrl: 'home.html',
                    controller: 'IndexController',
                    controllerAs: 'vm'
                });
    }
})();

我們使用的這種寫法有幾個地方需要注意:

  1. 通過IIFE風格的編碼瓢宦,使代碼在聲明后立刻被運行;
(function(){
})()
  1. 只在xxx.module文件中對angular.module進行setter操作
    angular
        .module('app', [
            'ui.router'     
        ])

module('name',[]) 為setter灰羽,即聲明一個新的module至angular上下文

  1. 通過module.config,controlle,service方法將關(guān)聯(lián)組件加入對應(yīng)的module中
       angular
        .module('app', [
            'ui.router'     
        ])
       .config(routeConfig);   
      // 等價于angular.module('app').config(routeConfig)
  1. 將相關(guān)的實現(xiàn)函數(shù)單獨放下而不是通過config(function(){})進行聲明驮履,增加可讀性
  2. 通過$inject方法來控制注入,而不是通過參數(shù)對比注入
//一般我們的做法可能是
    function routeConfig(['$stateProvider', '$urlRouterProvider', '$locationProvider'],$stateProvider, $urlRouterProvider, $locationProvider){
}

這樣通過參數(shù)控制的注入廉嚼,一般會有順序問題玫镐,參數(shù)一多,每次找的問題的時候必須先要進行“排排坐吃果果”的比較怠噪。推薦使用$inject來控制注入

    routeConfig.$inject = ['$stateProvider', '$urlRouterProvider','$locationProvider'];  

在實際聲明部分便需要需要再次聲明注入的形式的

  function routeConfig($stateProvider, $urlRouterProvider, $locationProvider)
    {
    }

通過 ui-router來創(chuàng)建一個/home的路由

我們通過ui-router的stateProvider來增加一個新的state home,其訪問的url為/home

 function routeConfig($stateProvider, $urlRouterProvider, $locationProvider)
    {

        $stateProvider
                .state('home', {
                    url: '/home',
                    templateUrl: 'home.html',
                    controller: 'IndexController',
                    controllerAs: 'vm'  //使用vm而不是$scope
                });
    }

而home.html的內(nèi)容為,這里我們使用了controller as vm的方法來訪問IndexController中的實例變量恐似,而不是使用$scope。至于這是為了什么傍念,可以閱讀我之前的說明或者谷歌一些相關(guān)的討論矫夷。
視圖中我們將在h1便簽部分顯示controller中的name變量的值,并且將其綁定與input的文本輸入框中憋槐,當用戶填寫新的文本值時双藕,會出修改name的值,從而上面h1顯示的值也會發(fā)生變化阳仔。

<h1>Hello {{vm.name}}</h1>
<label>input your name:</label>
<input ng-model="vm.name"></input>

那么對應(yīng)的我們也要寫一個IndexController

\\ app/scripts/index.controller.js
(function ()
{
    'use strict';

    angular
        .module('app')
        .controller('IndexController', IndexController);

    function IndexController()
    {
        var vm = this;  // 將this指針更名為vm
        vm.name = "unknown";  //初始化頁面的name 為 unknown
    }
})();

在index.html中引入module與contoller

  <body>
     <div ui-view>
    </div>
    <script src="bower_components/angular/angular.js"></script>
    <script src="bower_components/angular-ui-router/release/angular-ui-router.js"></script>
    <script src="scripts/index.module.js"></script>
    <script src="scripts/index.controller.js"></script>
  </body>

訪問 127.0.0.1:8080/#/home

這時便可看到頁面顯示了預(yù)期的效果忧陪,每當我們在文本框輸入新的值上方的顯示值則同步更新。這就是angular雙向綁定的優(yōu)勢之處。

下一期我們會做什么

我們會使用angular中的service來封裝一些外部的API編寫一個顯示當前天氣信息的小應(yīng)用嘶摊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末延蟹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子叶堆,更是在濱河造成了極大的恐慌阱飘,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虱颗,死亡現(xiàn)場離奇詭異俯萌,居然都是意外死亡,警方通過查閱死者的電腦和手機上枕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弱恒,“玉大人辨萍,你說我怎么就攤上這事》档” “怎么了锈玉?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長义起。 經(jīng)常有香客問我拉背,道長,這世上最難降的妖魔是什么默终? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任椅棺,我火速辦了婚禮,結(jié)果婚禮上齐蔽,老公的妹妹穿的比我還像新娘两疚。我一直安慰自己,他們只是感情好含滴,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布诱渤。 她就那樣靜靜地躺著,像睡著了一般谈况。 火紅的嫁衣襯著肌膚如雪勺美。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天碑韵,我揣著相機與錄音赡茸,去河邊找鬼。 笑死泼诱,一個胖子當著我的面吹牛坛掠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼屉栓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了友多?” 一聲冷哼從身側(cè)響起牲平,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎域滥,沒想到半個月后纵柿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡启绰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年昂儒,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片委可。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡渊跋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出着倾,到底是詐尸還是另有隱情拾酝,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布卡者,位于F島的核電站蒿囤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏崇决。R本人自食惡果不足惜材诽,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望恒傻。 院中可真熱鬧岳守,春花似錦、人聲如沸碌冶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽扑庞。三九已至譬重,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間罐氨,已是汗流浹背臀规。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留栅隐,地道東北人塔嬉。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓玩徊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谨究。 傳聞我的和親對象是個殘疾皇子恩袱,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容