AngularJS初級(jí)入門

通過AngularJS仿豆瓣一刻的案例:https://github.com/zhongxiaolian/douban

AngularJS介紹

AngularJS是一款由Google公司開發(fā)維護(hù)的前端MVC框架季二,其克服了HTML在構(gòu)建應(yīng)用上的諸多不足,從而降低了開發(fā)成本提高了開發(fā)效率。
AngularJS和jQuery是有一定區(qū)別的摩疑,jQuery更準(zhǔn)確的來說只是一個(gè)類庫(類庫指的是一系列函數(shù)的集合)以DOM作為驅(qū)動(dòng)搞挣,而AngularJS則是一個(gè)框架(諸多類庫的集合)以數(shù)據(jù)和邏輯作為驅(qū)動(dòng)置济。
框架對(duì)開發(fā)的流程和模式做了約束壹瘟,開發(fā)者需要遵照約束進(jìn)行開發(fā)阅签,更注重實(shí)際的業(yè)務(wù)邏輯矿瘦。

MVC

在開始學(xué)習(xí)AngularJS之前需要先了解什么是MVC枕面。它不是一種技術(shù),而是一種開發(fā)模式缚去,更準(zhǔn)確的說是組織代碼結(jié)構(gòu)的方式潮秘,廣泛應(yīng)用于軟件開發(fā)領(lǐng)域,更多應(yīng)用在后端開發(fā)程序里易结,在最初的前端開發(fā)的過程中js,css,html混在一起枕荞,代碼的結(jié)構(gòu)十分混亂,而且代碼之間的耦合度比較高搞动,不利于后期代碼的維護(hù)买猖,后來被引入到前端開發(fā)中,由于受到前端技術(shù)的限制便有了一些調(diào)整滋尉,進(jìn)而出現(xiàn)了很多MVC的衍生版(子集)如MVVM玉控、MVW、MVP狮惜、MV*等高诺。
MVC由模型(Model)、視圖(View)碾篡、控制器(Controller)3部分構(gòu)成虱而,采用這種開發(fā)模式為合理組織代碼、降低代碼間耦合度提供了方便开泽。
模型:一般用來處理數(shù)據(jù)牡拇,一般指操作數(shù)據(jù)庫。
視圖:一般用來展示數(shù)據(jù)穆律,比如通過HTML展示惠呼。
控制器:一般用做連接模型和視圖的橋梁。
接下來就該進(jìn)入正題了峦耘。剔蹋。。辅髓。泣崩。

模塊化

使用AngularJS構(gòu)建應(yīng)用(APP)時(shí)是以模塊化(module)的方式組織的少梁,即將整個(gè)應(yīng)用劃分為若干個(gè)模塊,每個(gè)模塊都有各自的職責(zé)矫付,最終組合成一個(gè)整體凯沪。
采用模塊化的組織方式可以最大程度的實(shí)現(xiàn)代碼的復(fù)用,可以像搭積木一樣進(jìn)行開發(fā)买优。

  • 定義應(yīng)用

通過為任一個(gè)HTML標(biāo)簽添加ng-app屬性著洼,可以指定一個(gè)應(yīng)用,表示此標(biāo)簽所包裹的內(nèi)容都屬于應(yīng)用(APP)而叼。一般在HTML標(biāo)簽上添加身笤。

<html lang="en" ng-app="App">
  • 定義模塊

AngularJS提供了一個(gè)全局對(duì)象angular,在此全局對(duì)象下存在若干個(gè)方法葵陵,其中angular.module()方法用來定義一個(gè)模塊液荸。

//第一個(gè)參數(shù)表示模塊的名稱,第二個(gè)參數(shù)表示此模塊依賴的其他模塊脱篙。
var App = angular.module('App', []);
  • 定義控制器

控制器作為連接模型和視圖的橋梁而存在娇钱,所以當(dāng)我們定義好了控制器也就定義好了模型和視圖。

//App是一個(gè)模塊實(shí)例绊困,通過模塊實(shí)例定義控制器文搂。
//第一個(gè)參數(shù)表示控制器的名稱,第二個(gè)參數(shù)是一個(gè)數(shù)組秤朗。
//除了數(shù)組的最后一個(gè)元素是函數(shù)外煤蹭,其余元素都是字符串,表明該控制器所依賴的服務(wù)取视。
App.controller('DemoContoller', ['$scope', function ($scope) {
    //$scope模型對(duì)象
    $scope.name = 'liangyiluo';
    $scope.school = '華北理工大學(xué)'; 
    $scope.courses = [
        'MVC',
        '指令',
        '模塊化'
    ]
}]);

模型數(shù)據(jù)要展示到視圖上硝皂,所以需要將控制器關(guān)聯(lián)到視圖上,通過為HTML標(biāo)簽添加ng-controller屬性并賦值相應(yīng)的控制器的名稱作谭,就確立了關(guān)聯(lián)關(guān)系稽物。

<div ng-controller="DemoContoller">
    <h1>{{name}}在{{school}}學(xué)習(xí)使用AngularJS</h1>
    <ul>
        <li ng-repeat="(key, course) in courses">第{{key+1}}天:{{course}}</li>
    </ul>
</div>

以上就是AngularJS最基本的MVC工作模式。所以的AngularJS學(xué)習(xí)都會(huì)圍繞下圖展開折欠。


AngularJS運(yùn)行架構(gòu).png

指令

HTML在構(gòu)建應(yīng)用(APP)時(shí)存在諸多不足贝或,AngularJS通過擴(kuò)展一系列的HTML屬性或標(biāo)簽來彌補(bǔ)這些缺陷,所謂指令就是就是AngularJS自定義的一系列的HTML屬性或標(biāo)簽锐秦。這些指令都是以ng-作為前綴的咪奖。

  • 內(nèi)置指令
    ng-app:指定應(yīng)用根元素,至少有一個(gè)元素指定了此屬性农猬。
    ng-controller:指定控制器赡艰。
    ng-show:控制元素是否顯示,true顯示斤葱,false不顯示慷垮。
    ng-hide:控制元素是否隱藏,true隱藏揍堕,false不隱藏料身。
    ng-if:控制標(biāo)簽是否存在,true存在衩茸,false不存在芹血。
    ng-src:圖片路徑。
    ng-href:文件地址楞慈。
    ng-class:控制類名幔烛。{"class1":true,"class2":true}
    ng-include:引入模版。js不能讀取文件囊蓝,所以需要向服務(wù)器發(fā)送ajax請(qǐng)求模版饿悬。一般用于將多個(gè)頁面的共同的頭和尾抽離出來。
    ng-disabled:表單禁用聚霜。
    ng-readonlu:表單只讀狡恬。
    ng-checked:單/復(fù)選框選中。
    ng-selected:下拉框選中蝎宇。
    注:更多指令請(qǐng)參照官方文檔弟劲。
  • 自定義指令
    AngularJS允許根據(jù)實(shí)際業(yè)務(wù)需要自定義指令,通過angular全局對(duì)象下的directive方法實(shí)現(xiàn)姥芥。
App.directive('tag', function () {
    return {
        // E element
        // A attribute
        // C class
        // M mark replace 必須為true
        restrict: 'ECMA',
        // template: '<ul><li>首頁</li><li>列表</li></ul>',
        templateUrl: './list.html',
        // replace: true
    }
});

數(shù)據(jù)綁定

AngularJS是以數(shù)據(jù)作為驅(qū)動(dòng)的MVC框架兔乞,所有模型里的數(shù)據(jù)經(jīng)過控制器展示到視圖中。
所謂數(shù)據(jù)綁定就是將模型中的數(shù)據(jù)與對(duì)應(yīng)的視圖進(jìn)行關(guān)聯(lián)凉唐,分為單向綁定和雙向綁定兩種方式报嵌。

  • 單向綁定
<body ng-app="App">
    <ul ng-controller="DemoController">
        <li ng-bind="name"></li>
        <li ng-cloak>{{name}}{{age}}</li>
        <li ng-bind-template="{{name}}{{age}}"></li>
    </ul>
    <script src="./libs/angular.min.js"></script>
    <script>
        var App = angular.module('App', []);
        App.controller('DemoController', ['$scope', function ($scope) {
            //只能加模型中的數(shù)據(jù)放到視圖上。
            $scope.name = 'itcast';
            $scope.age = 10;
        }]);
    </script> 
</body>
  • 雙向綁定
    雙向綁定可以實(shí)現(xiàn)模型數(shù)據(jù)和視圖模版的雙向傳遞熊榛。
    在AngularJS中通過{{}}或者ng-bind指令來實(shí)現(xiàn)模型數(shù)據(jù)向視圖模版的綁定锚国,模型數(shù)據(jù)通過一個(gè)內(nèi)置服務(wù)$scope來提供,這個(gè)$scope是一個(gè)空對(duì)象玄坦,通過為這個(gè)對(duì)象添加屬性或者方法便可以在相應(yīng)的視圖模版里被訪問血筑。
    注:{{}}在獲取數(shù)據(jù)時(shí)當(dāng)頁面刷新會(huì)有“閃爍”現(xiàn)象,給HTML標(biāo)簽添加ng-cloak可以解決(因?yàn)樵陧撁婕虞d時(shí)解析到{{}}時(shí)煎楣,頁面無法解析豺总,只有當(dāng)angular.js文件被加載后才可以解析,所以把a(bǔ)ngular.js文件提前也可以解決這個(gè)問題)择懂。通過ng-bind-template可以綁定多個(gè)數(shù)據(jù)喻喳。
    通過為表單元素添加ng-model指令實(shí)現(xiàn)視圖模版向模型數(shù)據(jù)的綁定。
<body ng-app="App">
    <div ng-controller="DemoController">
        <!-- 要實(shí)現(xiàn)數(shù)據(jù)從視圖向模型傳遞需要借助于表單元素 -->
        <input type="text" ng-model="msg">
        <h4>{{msg}}</h4>
        <button ng-click="show()">顯示</button>
    </div>
    <script src="./libs/angular.min.js"></script>
    <script>
        var App = angular.module('App', []);
        App.controller('DemoController', ['$scope', function ($scope) {
            $scope.show = function () {
                alert($scope.msg);
            }
        }]);
    </script>
</body>
  • 事件綁定
    AngularJS對(duì)事件也進(jìn)行了擴(kuò)展困曙,通過在原有事件名稱的基礎(chǔ)上添加ng-前綴表伦,然后以屬性的形式添加到對(duì)應(yīng)的HTML標(biāo)簽上即可谦去,如ng-click、ng-dbclick等蹦哼。
<body>
    <div ng-controller="DemoController">
        <ul>
            <li><button ng-click="single()">單擊</button></li>
        </ul>
    </div>
    <script src="./libs/angular.min.js"></script>
    <script>
        var App = angular.module('App', []);
        App.controller('DemoController', ['$scope', function ($scope) {
            $scope.single = function () {
                alert('我被單擊了');
            }
        }])
    </script>
</body>

通過ng-repeat可以將數(shù)據(jù)遍歷到視圖中

<body ng-app="Demo">
    
    <table>
        <thead>
            <tr>
                <th>姓名</th>
                <th>性別</th>
                <th>年齡</th>
            </tr>
        </thead>
        <tbody ng-controller="StarsController">
            <tr ng-repeat="star in stars">
                <td>{{star.name}}</td>
                <td>{{star.sex}}</td>
                <td>{{star.age}}</td>
            </tr>
        </tbody>
    </table>
    <script src="./libs/angular.min.js"></script>
    <script>
        var Demo = angular.module('Demo', []);
        Demo.controller('StarsController', ['$scope', function ($scope) {
            // 后面數(shù)據(jù)會(huì)來自于后端
            $scope.stars = [
                {name: '小紅', sex: '男', age: 62},
                {name: '小強(qiáng)', sex: '男', age: 40},
                {name: '小美', sex: '男', age: 39},
                {name: '小明', sex: '女', age: 12}
            ];
        }]);
    </script>
</body>

通過ng-switch on可以對(duì)數(shù)據(jù)進(jìn)行篩選(類似switch)

<body>
    <div ng-controller="DemoController">
        <ul>
            <li ng-repeat="item in items" ng-switch="item">
                <span ng-switch-when="css">{{item}}</span>
            </li>
        </ul>
    </div>
    <script src="./libs/angular.min.js"></script>
    <script>
        var App = angular.module('App', []);
        App.controller('DemoController', ['$scope', function ($scope) {
            $scope.items = ['html', 'css', 'js'];
        }]);
    </script>
</body>
  • 不同控制器之間的數(shù)據(jù)傳遞
    NG中多模塊開發(fā)不是多個(gè)模塊再去使用多個(gè)ng-app鳄哭,而是先確定主模塊,其他的子模塊添加到主模塊的中括號(hào)中纲熏,進(jìn)行注入妆丘。那么在主模塊中就可以使用子模塊了。
    可以參照具體項(xiàng)目:https://github.com/zhongxiaolian/douban
    那么繼續(xù)研究控制器之間的數(shù)據(jù)傳遞局劲。
   var app=angular.module('mainApp',[]);
   app.controller('SelfCtrl', function($scope) {
    $scope.click = function () {
        //$broadcast廣播to-child事件的名稱勺拣,廣播的內(nèi)容是child
        $scope.$broadcast('to-child', 'child');
        //$emit事件發(fā)射器to-parent是事件的名稱  parent是傳的內(nèi)容
        $scope.$emit('to-parent', 'parent');
    }
   });
   app.controller('ParentCtrl', function($scope) {
    $scope.$on('to-parent', function(event,data) {
        console.log('ParentCtrl', data);          
    });
    });
app.controller('ChildCtrl', function($scope){
    $scope.$on('to-child', function(event,data) {
        console.log('ChildCtrl', data);      
    });
});

作用域

通常AngularJS中應(yīng)用是由若干個(gè)視圖組合而成的,而視圖又都是HTML元素鱼填,并且HTML元素是可以相互嵌套的药有,另一方面視圖都隸屬于某個(gè)控制器,進(jìn)而控制器之間也必然會(huì)存在嵌套關(guān)系剔氏。每個(gè)控制器又對(duì)應(yīng)一個(gè)模型也就是$scope對(duì)象塑猖,不同層級(jí)控制器下的$scope便產(chǎn)生了作用域。

  • 根作用域
    一個(gè)AngularJS應(yīng)用在啟動(dòng)時(shí)會(huì)自動(dòng)創(chuàng)建一個(gè)根作用域$rootScope谈跛,這個(gè)根作用域在整個(gè)應(yīng)用范圍都是可以被訪問到的羊苟。
//在根作用域初始化數(shù)據(jù)
<body ng-init="name='itcast';age=10">
</body>
  • 子作用域
    通過ng-controller指令可以創(chuàng)建一個(gè)子作用域,新建的作用域可以訪問其父作用域中的數(shù)據(jù)感憾。

過濾器

在AngularJS中使用過濾器格式化展示數(shù)據(jù)蜡励,在{{}}中使用 “|”來調(diào)用過濾器,使用“:”傳遞參數(shù)阻桅。

  • 內(nèi)置過濾器
    1凉倚、currency;將數(shù)值格式轉(zhuǎn)換為貨幣格式
    2、date:格式化日期
    3嫂沉、filter:在給定數(shù)組中選擇滿足條件的一個(gè)子集稽寒,并返回一個(gè)新數(shù)組,其條件可以是一個(gè)字符串趟章、對(duì)象杏糙、函數(shù)。
    4蚓土、json:將javascript對(duì)象轉(zhuǎn)換為JSON字符串宏侍。
    5、limitTo:取出字符串或數(shù)組的前(正數(shù))幾位或者后(負(fù)數(shù))幾位蜀漆。
    6谅河、lowercase:轉(zhuǎn)小寫
    7、uppercase:轉(zhuǎn)大寫
    8、number:數(shù)字格式化绷耍,可控制小數(shù)位數(shù)吐限。
    9、orderby:對(duì)數(shù)組進(jìn)行排序锨天,第二個(gè)參數(shù)可控制方向毯盈。
<body ng-app="App">
    <ul ng-controller="DemoController">
        <!--加貨幣前綴-->
        <li>{{price|currency:'¥'}}</li>
        <!--日期格式化-->
        <li>{{now|date:'yyyy/MM/dd hh:mm:ss'}}</li>
        <!--遍歷數(shù)組過濾包含's'字符的元素-->
        <li>{{items|filter:'s'}}</li>
        <!--過濾包含age屬性剃毒,并且值為16的對(duì)象-->
        <li>{{students|filter:{age: 16} }}</li>
        <!--將js對(duì)象轉(zhuǎn)換為json-->
        <li>{{students|json}}</li>
        <!--從后向前取兩個(gè)-->
        <li>{{items|limitTo:-2}}</li>
        <!--所有字符轉(zhuǎn)大寫病袄,并從前向后找3個(gè)-->
        <li>{{str|uppercase|limitTo:3}}</li>
        <!--轉(zhuǎn)小寫-->
        <li>{{str|lowercase}}</li>
        <!--保留兩位小數(shù)-->
        <li>{{num|number:2}}</li>
        <!--第一個(gè)參數(shù)為要比較的屬性值,第二個(gè)參數(shù)true代表降序赘阀,false代表升序益缠。-->
        <li>{{items|orderBy: '':false}}</li>
        <li>{{students|orderBy: 'age': true}}</li>
    </ul>
    <script src="./libs/angular.min.js"></script>
    <script>
        var App = angular.module('App', []);
        App.controller('DemoController', ['$scope', function ($scope) {
            $scope.price = 11.11;
            $scope.now = new Date;
            $scope.items = ['html', 'css', 'js'];
            $scope.students = [
                {name: '小紅', age: 16},
                {name: '小明', age: 17},
                {name: '小米', age: 10}
            ];
            $scope.str = 'hello Angular';
            $scope.num = '10.2345';
        }]);
    </script>
</body>
  • 自定義過濾器
    除了使用AngularJS內(nèi)置的過濾器外,還可以根據(jù)業(yè)務(wù)需要自定義過濾器基公,通過模塊實(shí)例對(duì)象的filter方法自定義過濾器幅慌。
var App = angular.module('App', []);
//這個(gè)過濾器要實(shí)現(xiàn)的功能是首字母大寫
App.filter('capitalize', function () {
//過濾器實(shí)際上就是一個(gè)函數(shù),第一個(gè)參數(shù)表示要處理的數(shù)據(jù)轰豆,第二個(gè)參數(shù)表示給過濾器傳遞的參數(shù)胰伍。
    return function (input, arg2) {
        return input[0].toUpperCase() + input.slice(1);
    }
});

依賴注入

AngularJS采用模塊化的方式組織代碼,將一些邏輯封裝成一個(gè)對(duì)象或函數(shù)酸休,實(shí)現(xiàn)最大程度復(fù)用骂租,這導(dǎo)致了使用者和被使用者之間存在依賴關(guān)系。
所謂依賴注入是指在運(yùn)行時(shí)自動(dòng)查找依賴關(guān)系斑司,找到后傳遞給使用者的一種機(jī)制渗饮。
常見的AngularJS的內(nèi)置服務(wù)有$http、$location宿刮、$timeout互站、$rootScope等。

  • 推斷式注入
    沒有明確聲明依賴僵缺,AngularJS會(huì)將函數(shù)參數(shù)名稱當(dāng)成是依賴的名稱胡桃。
var App = angular.module('App', []);
App.controller('DemoController', function ($scope, $http) {
});

注:這種方式存在一個(gè)問題,當(dāng)代碼壓縮后函數(shù)的參數(shù)被壓縮磕潮,這樣便會(huì)造成依賴無法找到翠胰。

  • 行內(nèi)注入
    以數(shù)組形式明確聲明依賴關(guān)系,數(shù)組元素都是包含依賴名稱的字符串揉抵,數(shù)組最后一個(gè)元素是依賴注入的目標(biāo)函數(shù)亡容。
var App = angular.module('App', []);
// 行內(nèi)式注入,推薦使用這種依賴注入方式冤今。
App.controller('DemoController', ['$scope', '$http', function ($scope, $http) {
    $scope.name = '依賴注入';
}]);

服務(wù)

服務(wù)是一個(gè)對(duì)象或函數(shù)闺兢,對(duì)外提供特定的功能。

  • 內(nèi)置服務(wù)
    1、$location是對(duì)原生Javascript的location對(duì)象的屬性和方法的封裝屋谭。
    2脚囊、$timeout和$interval對(duì)原生Javascript的setTimeout和setInterval進(jìn)行了封裝。
var App = angular.module('App', []);
App.controller('DemoController', ['$scope', '$timeout', '$interval',function ($scope, $timeout, $interval) {
    $timeout(function () {
        $scope.msg = '執(zhí)行了';
    }, 3000);
    var timer = $interval(function () {
        $scope.now = new Date;
    }, 1000);
    $scope.stop = function () {
        $interval.cancel(timer);
    }
}]);
  • $filter在控制器中格式化數(shù)據(jù)
var App = angular.module('App', []);
App.controller('DemoController', ['$scope', '$filter', function ($scope, $filter) {
    $scope.price = 11.11;
    var currency = $filter('currency');
    $scope.price = currency($scope.price,"¥");
    $scope.str = 'hello angular';
    var uppercase = $filter('uppercase');
    $scope.str = uppercase($scope.str);
    $scope.str1 = $filter('limitTo')($scope.str, 2);
}]);
  • $log打印調(diào)試信息
var App = angular.module('App', []);
App.controller('DemoController', ['$log', function ($log) {
    $log.info('普通信息');
    $log.warn('警告信息');
    $log.error('錯(cuò)誤信息');
    $log.log('打印信息');
    $log.debug('調(diào)試信息');
}]);
  • $http用于向服務(wù)器發(fā)ajax請(qǐng)求
var App = angular.module('App', []);
App.controller('DemoController', ['$scope', '$http', '$log', function ($scope, $http, $log) {
    $http({
        url: 'example.php',
        method: 'post',
        headers: {
            // 'Content-Type': 'application/x-www-form-urlencoded'
            //上面這種請(qǐng)求頭會(huì)把請(qǐng)求數(shù)據(jù)設(shè)置成form-data形式
            'Content-Type': 'application/json;charset=UTF-8' 
            //默認(rèn)的請(qǐng)求頭信息(Restful 發(fā)送的是JSON數(shù)據(jù))
        },
        // get 參數(shù)
        params: { 
            name: 'itcast',
            sex: '男'
        }
        // post參數(shù)   
        data: { 
            age: 10
        }
    }).success(function (info) {
        $log.info(info);
    });
}]);
// 接口方式
// SOAP(key=val&key=val桐磁,這種形式叫formData悔耘,Content-Type 設(shè)成 application/x-www-form-urlencoded,PHP后臺(tái)可以用$_POST來接收) 
// RESTFUL(json數(shù)據(jù)我擂,這種形式叫Request Payload衬以,Content-Type 設(shè)成 application/json;charset=UTF-8,也是默認(rèn)的校摩,PHP后臺(tái)可以用file_get_contents("php://input") )

通過JSONP獲取天氣信息

var App = angular.module('App', []);
App.controller('WeatherController', ['$scope', '$http', function($scope, $http) {
    $http({
        method: 'jsonp', // 支持jsonp
        //callback=JSON_CALLBACK是固定寫法看峻,服務(wù)器默認(rèn)獲取callback屬性值,JSON_CALLBACK是一個(gè)占位符衙吩,AngularJS底層會(huì)自動(dòng)生成一個(gè)函數(shù)替換它(被服務(wù)器調(diào)用互妓,接收服務(wù)器返回的數(shù)據(jù))。
        url: 'http://api.map.baidu.com/telematics/v3/weather?callback=JSON_CALLBACK',
        params: {
            location: '北京',
            output: 'json',
            ak: '0A5bc3c4fb543c8f9bc54b77bc155724'
        }
    })
    .success(function (data) {
        // 請(qǐng)求回的數(shù)據(jù)放到模型上
        $scope.weatherData = data.results[0].weather_data;
    });
}])
  • 自定義服務(wù)
    手動(dòng)將一些通用性的邏輯功能進(jìn)行封裝坤塞,方便以后使用冯勉。服務(wù)本質(zhì)上就是一個(gè)對(duì)象或函數(shù),所以自定義服務(wù)就是要返回一個(gè)對(duì)象或函數(shù)以供使用摹芙。
    1灼狰、factory方法
var App = angular.module('App', []);
// 通過factory定義一個(gè)名叫showTime的服務(wù)
App.factory('showTime', ['$filter', function ($filter) {
    var now = new Date();
    var date = $filter('date');
    return {
        now: date(now, 'y-M-d H:m:s')
    }
}]);
App.controller('DemoController', ['$scope', 'showTime', function($scope, showTime) {
    $scope.now = showTime.now;
}])

2、service方法

var App = angular.module('App', []);
// 通過service方法自定義服務(wù)顯示日期
App.service('showTime', ['$filter', function($filter) {
    var now = new Date();
    var date = $filter('date');
    //不需要return瘫辩,直接賦值給this
    this.now = date(now, 'y-M-d H:mm:ss');
}]);
App.controller('DemoController', ['$scope', 'showTime', function($scope, showTime) {
    $scope.now = showTime.now;
}])

3伏嗜、value方法

var App = angular.module('App', []);
// 自定義常量服務(wù)
App.value('author', 'itcast');
App.value('version', '1.0');
// 本質(zhì)上是一個(gè)服務(wù)
// 從表現(xiàn)形式上是一個(gè)常量
// 常量就是不變的值與變量相對(duì)應(yīng)
// 聲明依賴調(diào)用服務(wù)
App.controller('DemoController', ['$scope', 'author', 'version', function($scope, author, version) {
    $scope.author = author;
    $scope.ver = version;
}]);

模塊加載

AngularJS模塊可以在被加載和執(zhí)行之前對(duì)其自身進(jìn)行配置。

AngularJS執(zhí)行流程.png
  • 配置模塊
    通過config方法實(shí)現(xiàn)對(duì)模塊的配置伐厌,AngularJS中的服務(wù)大部分都對(duì)應(yīng)一個(gè)provider承绸,用來執(zhí)行與對(duì)應(yīng)服務(wù)相同的功能或?qū)ζ溥M(jìn)行配置。
    比如$log挣轨,$http军熏,$location都是內(nèi)置服務(wù),相對(duì)應(yīng)的provider分別是$logProvider卷扮,$httpProvider荡澎,$locationProvider。
    下面以$log和$filter模塊為例進(jìn)行演示:
<body>
    <div ng-controller="DemoController">
        <h1>{{now}}</h1>
        <h2>{{str|capitalize}}</h2>
    </div>
    <script src="./libs/angular.min.js"></script>
    <script>
        var App = angular.module('App', []);
        // 配置$log服務(wù)(禁用debug)
        // 允許一次配置多個(gè)服務(wù)(模塊)晤锹, 傳遞的一個(gè)數(shù)組(依賴注入方式)
        App.config(['$logProvider', '$filterProvider', function ($logProvider, $filterProvider) {
            // 禁用debug功能
            $logProvider.debugEnabled(false);
            // 默認(rèn)9個(gè)過濾器摩幔,通過配置可以新增一些過濾器
            $filterProvider.register('capitalize', function () {
                // 新增一個(gè)過濾器
                return function (input) {
                    return input[0].toUpperCase() + input.slice(1);
                }
            });
        }]);
        //視圖和模型綁定演示剛剛配置的過濾器
        App.controller('DemoController', ['$scope', '$log', function ($scope, $log) {
            // 測(cè)試配置后的結(jié)果
            $log.debug('debug');
            $scope.str = 'hello angular';
        }]);
    </script>
</body>
  • 運(yùn)行模塊
    服務(wù)是以模塊的形式存在的且對(duì)外提供特定的功能,之前都是將服務(wù)作為依賴鞭铆,注入到相應(yīng)的控制器或衡,然后在控制器中進(jìn)行調(diào)用,除了這種方式我們還可以直接運(yùn)行服務(wù)模塊,AngularJS提供了run方法封断。
<body>
    <div ng-controller="DemoController">
        {{name}}
    </div>
    <script src="./libs/angular.min.js"></script>
    <script>
        var App = angular.module('App', []);
        // 直接運(yùn)行$http斯辰、$rootScope服務(wù),沒有作為依賴項(xiàng)傳遞給其他模塊坡疼。
        // $rootScope是根作域
        App.run(['$http', '$rootScope', function ($http, $rootScope) {
            // 直接調(diào)用$http
            $http({
                url: 'example.php',
                method: 'get'
            });
            // 在根作用域賦值彬呻。
            $rootScope.name = '祖宗';
        }]);
        App.controller('DemoController', ['$scope', function($scope) {
            $scope.name = '后代';
        }]) 
    </script>
</body>

不但如此,run方法還是最先被執(zhí)行的柄瑰,利用這個(gè)功能我們可以將一些需要優(yōu)先執(zhí)行的功能通過run方法來運(yùn)行闸氮,比如驗(yàn)證用戶是否登錄,未登錄則不允許進(jìn)行任何操作狱意。

路由

  • 單頁面應(yīng)用的介紹
    一個(gè)應(yīng)用是由多個(gè)視圖組成的湖苞,需要根據(jù)不同的業(yè)務(wù)邏輯展示給用戶不同的視圖拯欧,路由則是實(shí)現(xiàn)這一功能的關(guān)鍵详囤,但頁面應(yīng)用可以提升性能,增強(qiáng)用戶體驗(yàn)镐作。
    SPA(Single Page Application):指的是通過單頁面展示所有功能藏姐,通過Ajax動(dòng)態(tài)獲取數(shù)據(jù)然后實(shí)時(shí)進(jìn)行渲染,結(jié)合CSS3動(dòng)畫模仿原生APP交互该贾,然后在進(jìn)行打包(使用工具把Web應(yīng)用包一個(gè)殼羔杨,這個(gè)殼本質(zhì)上就是一個(gè)瀏覽器)變成一個(gè)“原生應(yīng)用”。
    在PC端也有廣泛的應(yīng)用杨蛋,通常情況下使用Ajax異步請(qǐng)求數(shù)據(jù)兜材,然后實(shí)現(xiàn)內(nèi)容的局部刷新,局部刷新的本質(zhì)就是動(dòng)態(tài)生成DOM逞力,新生成的DOM元素并沒有真實(shí)存在于文檔中曙寡,所以當(dāng)再次刷新時(shí)新添加的DOM元素會(huì)“丟失”,通過單頁面應(yīng)用可以很好的解決這個(gè)問題寇荧。
    路由举庶。
  • 路由的使用
    在后端開發(fā)過程中通過URL地址可以實(shí)現(xiàn)頁面(視圖)的切換,但是AngularJS是一個(gè)純前端的MVC框架揩抡,在開發(fā)但頁面應(yīng)用時(shí)户侥,所有功能都在同一頁面完成,所以無需切換URL地址(即不允許產(chǎn)生跳轉(zhuǎn))峦嗤,但WEB應(yīng)用中又經(jīng)常通過鏈接(a標(biāo)簽)來更新頁面(視圖)蕊唐,當(dāng)點(diǎn)擊鏈接時(shí)還要阻止其向服務(wù)器發(fā)起請(qǐng)求,通過錨點(diǎn)(頁內(nèi)跳轉(zhuǎn))可以實(shí)現(xiàn)這一點(diǎn)烁设。
    實(shí)現(xiàn)單頁面應(yīng)用需要具備:
    1替梨、只有一個(gè)頁面。
    2、鏈接使用錨點(diǎn)耙替。
    3亚侠、服務(wù)器。
    下面是一個(gè)簡單的使用NG路由的例子:
<body>
    <div class="wrapper">
        <!-- 導(dǎo)航菜單 -->
        <ul>
            <li>
                <a href="#/contact/5/abc/7">Contact Us</a>
            </li>
            <li>
                <a href="#/list">List</a>
            </li>
        </ul>
        <div class="content">
            <!-- 占位符 -->
            <div ng-view></div>
        </div>
    </div>
    <!-- AngularJS核心框架 -->
    <script src="./libs/angular.min.js"></script>
    <!-- 路由模塊理解成NG插件 -->
    <script src="./libs/angular-route.js"></script>
    <script>
        // 依賴ngRoute模塊
        var App = angular.module('App', ['ngRoute']);
        // 需要對(duì)路由模塊進(jìn)行配置俗扇,使其正常工作
        App.config(['$routeProvider', function ($routeProvider) {
            $routeProvider.when('/contact/:id/:page/:p', {
                templateUrl: './contact.html',
                controller: 'ContactController' // 定義控制器
            })
            .when('/list', {
                templateUrl: './list.html', // 視圖模板
                controller: 'ListController' // 定義控制器
            })
            .otherwise({
                redirectTo: '/contact'
            });
        }]);
        App.controller('ListController', ['$scope', '$http', function ($scope, $http) {
            $http({
                url: '10-02.php',
            }).success(function (info) {
                $scope.items = info;
            });
        }]);
        App.controller('ContactController', ['$scope', '$http','$routeParams', function ($scope, $http,$routeParams) {
            console.log($routeParams);
            $http({
                url: 'contact.php'
            }).success(function (info) {
                $scope.content = info;
            });
        }]);
    </script>
</body>

單頁面應(yīng)用原理:

<body>
    <div class="wrapper">
        <!-- 導(dǎo)航菜單 -->
        <ul>
            <li class="active">
                <a href="#index">Index</a>
            </li>
            <li>
                <a href="#introduce">Introduce</a>
            </li>
            <li>
                <a href="#contact">Contact Us</a>
            </li>
        </ul>
        <!-- 內(nèi)容 -->
        <div class="content">
            Index Page
        </div>
    </div>
    <script>
        //和tab欄不同:
        //1硝烂、a標(biāo)簽不需要添加click事件
        //2、重復(fù)點(diǎn)擊不會(huì)多次觸發(fā)事件铜幽,因?yàn)閔ash并沒變滞谢。
        // 監(jiān)聽錨點(diǎn)變化然后發(fā)送請(qǐng)求
        // hashchange事件可以監(jiān)聽錨點(diǎn)變化
        window.addEventListener('hashchange', function () {
            // 獲取錨點(diǎn)
            var hash = location.hash;
            // 處理#
            hash = hash.slice(1);
            var xhr = new XMLHttpRequest;
            // 將錨點(diǎn)做為參數(shù)傳遞給服務(wù)端進(jìn)處理
            xhr.open('get', '10-01.php?hash=' + hash);
            xhr.send(null);
            xhr.onreadystatechange = function () {
                if(xhr.readyState == 4 && xhr.status == 200) {
                    var result = xhr.responseText;
                    // 將返回結(jié)果添加到頁面
                    document.querySelector('.content').innerHTML = result;
                }
            }
        });
    </script>
</body>

通過上面的例子發(fā)現(xiàn)可以通過監(jiān)聽hashchange事件監(jiān)聽到錨點(diǎn)的變化,進(jìn)而可以實(shí)現(xiàn)為不同的錨點(diǎn)綁定不同的視圖除抛,單頁面應(yīng)用就是基于這個(gè)原理實(shí)現(xiàn)的狮杨。
注:在1.2版本之前路由器的功能是包含在AngularJS核心代碼中的,之后的版本將路由器獨(dú)立成一個(gè)模塊到忽,下載angular-route.js橄教。

  • 路由參數(shù)
    1、$routeProvider提供兩個(gè)方法匹配路由喘漏,分別是when和otherwise护蝶,when需要兩個(gè)參數(shù),othersize方法作為when方法的補(bǔ)充只需要一個(gè)參數(shù)翩迈,其中when方法可以被多次調(diào)用持灰。
    2、第一個(gè)參數(shù)是一個(gè)字符串负饲,代表當(dāng)前URL的hash值堤魁。
    3、第二個(gè)參數(shù)是一個(gè)對(duì)象返十,用于配置當(dāng)前路由的視圖妥泉、控制器等。
    template:字符串形式的模版吧慢。
    templateURL:引入外部視圖模版涛漂。
    controller:視圖模版所屬的控制器。
    redirectTo:跳轉(zhuǎn)到其他路由检诗。
    4匈仗、獲取路由傳遞的參數(shù),在控制器中注入$routeParams可以獲取路由傳遞的參數(shù)逢慌。

內(nèi)置jQuery

在沒有引入jQuery之前悠轩,NG實(shí)現(xiàn)了簡版的jQuery Lite,通過angular.element不能選擇元素攻泼,但是可以將一個(gè)DOM元素轉(zhuǎn)換成jQuery對(duì)象火架,如果提前引入了jQuery則angular.element則完全等于jQuery鉴象。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市何鸡,隨后出現(xiàn)的幾起案子纺弊,更是在濱河造成了極大的恐慌,老刑警劉巖骡男,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淆游,死亡現(xiàn)場離奇詭異,居然都是意外死亡隔盛,警方通過查閱死者的電腦和手機(jī)犹菱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吮炕,“玉大人腊脱,你說我怎么就攤上這事×祝” “怎么了陕凹?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長俱笛。 經(jīng)常有香客問我捆姜,道長,這世上最難降的妖魔是什么迎膜? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮浆兰,結(jié)果婚禮上磕仅,老公的妹妹穿的比我還像新娘。我一直安慰自己簸呈,他們只是感情好榕订,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蜕便,像睡著了一般劫恒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上轿腺,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天两嘴,我揣著相機(jī)與錄音,去河邊找鬼族壳。 笑死憔辫,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的仿荆。 我是一名探鬼主播贰您,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼坏平,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了锦亦?” 一聲冷哼從身側(cè)響起舶替,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎杠园,沒想到半個(gè)月后坎穿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡返劲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年玲昧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片篮绿。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡孵延,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出亲配,到底是詐尸還是另有隱情尘应,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布吼虎,位于F島的核電站犬钢,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏思灰。R本人自食惡果不足惜玷犹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望洒疚。 院中可真熱鬧歹颓,春花似錦、人聲如沸油湖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乏德。三九已至撤奸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間喊括,已是汗流浹背胧瓜。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瘾晃,地道東北人贷痪。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像蹦误,于是被迫代替她去往敵國和親劫拢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肉津,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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