簡介
什么是AngularJS
- 一個功能非常完備的前端框架,通過增強HTML的方式提供一種便捷開發Web應用程序的方式
- 其核心特點就是幾乎無任何DOM操作,讓開發人員的精力和時間全部集中於業務
- MVC的特性增強了代碼的結構和可維護性,應對需求的變化做出最小的改動
為什么使用AngularJS
- 更少的代碼實現更強勁的功能
- 提供了很多在傳統后端開發中大量使用的思想和方式,提高前台代碼的結構和可維護性
使用AnuglarJS的流程
- 在HTML中引入Angular.js文件
- 在自己的代碼中定義一個AngularJS的模塊
- 將模塊作用到HTML中的某個節點
- 根據模塊的功能定義控制器
- 根據當前頁面原型設計$scope的結構
- 通過$scope暴露數據和行為
- 將暴露出來的數據和行為通過特定的指令綁定到HTML節點中
MVC
- 一種應用程序的設計思想,其目的是為了對應用程序的組成進行划分,讓結構更加清晰可維護性更高,確保每個原件都有明確的單一職責

模塊
- 可以通過
angular.module()方法操作模塊- 注意:該方法只有在傳入兩個參數時才會創建模塊,否則為獲取已有模塊
定義模塊
// 第一個參數為模塊名,第二個參數為當前這個模塊所依賴的模塊列表
angular.module('ModuleName', []);
獲取已經定義過的模塊
var existModule = angular.module('ExistModule');
如何划分模塊
1.根據當前需要開發的應用程序的組成划分需要多少模塊,
比如:
- 注冊模塊
- 登錄模塊
- 用戶列表頁模塊
- 用戶詳細頁模塊
- etc.
2. 根據文件類型的不同來划分
比如:
- 所有的控制器
- 所有的服務
- 所有的指令
- etc.
控制器
當下的企業開發,如果使用Angular,主要就是開發對應的控制器和模型
定義控制器
定義控制器可以有三種方式,注意第一種已經被淘汰
傳統方式(不要再用了)
在最早期的 Angular 代碼中可能會見到以全局函數的方式定義的控制器:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>早期的控制器定義方式-全局函數</title>
</head>
<body ng-app>
<div ng-controller="FooController">
<input type="button" value="clicked me!" ng-click="say()">
</div>
</body>
</html>
function FooController($scope) {
$scope.say = function(){
console.log('hello angular');
};
}
這種方式現在已經不被支持,就算沒有淘汰也不應該使用,太low(全局作用域的問題)
常用方式(掛載在某個模塊下)(必須掌握)
Angular中最常見的一種使用方式,通過模塊中定義的controller方法定義控制器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>常用方式(掛載在某個模塊下)</title>
</head>
<body ng-app="MyModule">
<div ng-controller="FooController">
<input type="button" value="clicked me!" ng-click="say()">
</div>
</body>
</html>
angular.module('MyModule', [])
.controller('FooController', function($scope) {
$scope.say = function(){
console.log('hello angular');
};
});
定義類型的方式(構造函數)
對於喜歡通過定義構造函數的方式編寫面向對象代碼的同學可以使用構造函數的形式定義一個控制器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>面向對象的方式</title>
</head>
<body ng-app="MyModule">
<div ng-controller="FooController as context">
<input type="button" value="clicked me!" ng-click="context.say()">
</div>
</body>
</html>
function FooController() {
this.message = 'hello angular';
}
FooController.prototype.say = function() {
console.log(this.message);
};
angular.module('MyModule', [])
.controller('FooController', FooController);
注意事項
- 在以上的使用方式中,如果需要為控制器函數注入類似
$scope之類的參數,必須確保參數名為一個特定值 - 也就是說Angular會根據參數名稱自動注入對應的對象(與參數個數,出現順序無關),所以參數名一定不能寫錯
- 但是,我們對於寫完的JS代碼經常會在上線之前對代碼進行壓縮
- 壓縮的過程中如果啟用混淆壓縮的話,就會造成參數名變化
- 一旦變化了參數名,NG就無法為其注入對應的對象了
所以,最安全的寫法就是不要依賴參數名(依賴不會變化的東西):
angular.module('MyModule', [])
.controller('FooController', ['$scope', function(whatever) {
whatever.say = function(){
console.log('hello angular');
};
}]);
解決方式就是將創建控制器的第二個參數改為一個數組,數組的最后一個成員就是以前的控制器函數,前面的成員就是控制器函數需要注入的對象列表,按照順序對應
擴展小知識:實現原理
如何根據參數名傳入特定對象?
function getFnParams(fn) {
if (typeof fn == 'function') {
var mathes = /.+\((.+)\)/.exec(Function.prototype.toString.call(fn));
if (mathes[1]) {
var args = mathes[1].replace(/\s/g, '').split(',');
return args;
}
}
}
function foo(id, name, a1ge) {}
console.log(getFnParams(foo));
$scope
- 視圖和控制器之間的數據橋梁
- 用於在視圖和控制器之間傳遞數據
- 用來暴露數據模型(數據,行為)

ViewModel
- $scope 實際上就是MVVM中所謂的VM(視圖模型)
- 正是因為$scope在Angular中大量使用甚至蓋過了C(控制器)的概念,所以很多人(包括我)把Angular稱之為MVVM框架
- 這一點倒是無所謂,具體看怎么用罷了
大家必須掌握的就是如何根據一個原型抽象出對應的視圖模型

表達式
類似於模版引擎的語法
作用:
使用表達式把數據綁定到 HTML。
語法:
- 表達式寫在雙大括號內:{{ expression }}。
- AngularJS 表達式很像 JavaScript 表達式
- 它們可以包含文字、運算符和變量
- 如 {{ 5 + 5 }} 或 {{ firstName + '-' + lastName }}
支持的類型
- 數字 {{ 100 + 100 }}
- 字符串 {{ 'hello' + 'angular' }}
- 對象 {{ zhangsan.name }}
- 數組 {{ students[10] }}
與JS的比較:
相同點:
- AngularJS 表達式可以包含字母,操作符,變量。
不同點:
- AngularJS 表達式可以寫在 HTML 中。
- AngularJS 表達式不支持條件判斷,循環及異常。
- AngularJS 表達式支持過濾器。
指令
- 在 AngularJS 中將前綴為 ng- 這種屬性稱之為指令,其作用就是為 DOM 元素調用方法、定義行為綁定數據等
- 簡單說:當一個 Angular 應用啟動,Angular 就會遍歷 DOM 樹來解析 HTML,根據指令不同,完成不同操作
指令標准屬性的問題
- ng-xxx 的屬性本身並不是標准中定義的屬性
- 很多情況下語法校驗是無法通過的
- HTML5 允許擴展的(自制的)屬性,以 data- 開頭。
- 在 AngularJS 中可以使用 data-ng- 來讓網頁對 HTML5 有效。
- 二者效果相同。
內置指令
ng-app
- ng-app 指令用來標明一個 AngularJS 應用程序
- 標記在一個 AngularJS 的作用范圍的根對象上
- 系統執行時會自動的執行根對象范圍內的其他指令
- 可以在同一個頁面創建多個 ng-app 節點(不推薦)
- 創建多個ng-app時,默認只能執行第一個,后面的需要手動引導:angular.bootstrap()
- 標記的范圍盡可能小,性能
ng-model
- 用於建立界面上的元素到數據模型屬性的雙向數據綁定
- 一般情況綁定到元素的value屬性上
- 但是在checkbox之類的表單元素會有不同
ng-bind
ng-bind-html
ng-repeat
ng-class
ng-cloak
ng-show/ng-hide/ng-if
ng-src
ng-switch
其他常用指令
- ng-checked:
- 單選/復選是否選中,只是單向綁定數據
- ng-selected:
- 是否選中,只是單向綁定數據
- ng-disabled:
- 是否禁用
- ng-readonly:
- 是否只讀
常用事件指令
不同於以上的功能性指令,Angular還定義了一些用於和事件綁定的指令:
- ng-blur:
- 失去焦點
- ng-change:
- 發生改變
- ng-copy:
- 拷貝完成
- ng-click:
- 單擊
- ng-dblclick:
- 雙擊
- ng-focus:
- 得到焦點
- ng-blur:
- 失去焦點
- ng-submit:
- 表單提交
自定義指令
- 指令無外乎增強了 HTML,提供額外的功能
- 以上的指令基本上已經可以滿足我們的絕大多數需要了
- 少數情況下我們有一些特殊的需要,可以通過自定義指令的方式實現:
組件式指令Demo
myModule.directive('hello', function() {
return {
restrict: 'E',
template: '<h1>Hello world</h1>',
replace: true
};
});
功能型指令Demo
myApp.directive("ngHover", function() {
return function(scope, element, attrs) {
element.bind("mouseenter", function() {
element.css("background", "yellow");
});
element.bind("mouseleave", function() {
element.css("background", "none");
});
}
});
自定義指令的類型
- E:Element(元素)
- A:Attribute(屬性)
- C:Class(類名)
- M:Comment(注釋)
注意:
在定義指令應該使用駝峰命名法,使用指令時應該使用的是全小寫字母中划線分割的方式
