一、angular介紹
1、angular是Google公司提供的一套基于MVC結(jié)構(gòu)的js開發(fā)工具,其核心功能就是對(duì)現(xiàn)有html編碼以指令方式進(jìn)行擴(kuò)展,并使其通過使用元素聲明的方式來構(gòu)建動(dòng)態(tài)內(nèi)容。
2、為實(shí)現(xiàn)上述目的,angular利用 了兩項(xiàng)技術(shù)點(diǎn):雙向綁定和依賴注入
二、適用范圍
angular是構(gòu)建一個(gè)MVC類結(jié)構(gòu)的js庫,建議在構(gòu)建CRUD應(yīng)用時(shí)使用它。對(duì)于圖形編輯、游戲開發(fā)不建議使用。
三、控制器
1、控制器功能是管理頁面的邏輯代碼。任務(wù)就是操作$scope對(duì)象。
2、當(dāng)ng-controller指令被添加到dom頁面上時(shí),angular通過構(gòu)造函數(shù)生成實(shí)體對(duì)象時(shí),$scope注入其中,$scope與頁面元素進(jìn)行數(shù)據(jù)綁定,實(shí)現(xiàn)數(shù)據(jù)從控制器到視圖層。
3、控制器是純 Javascript 構(gòu)造函數(shù),所以應(yīng)該用首字母大寫的駝峰命名法(HomePageCtrl, ShoppingCartCtrl, AdminPanelCtrl, 等等)。
4、使用 數(shù)組定義語法聲明控制器,如下
function MyCtrl($scope) {}
var myModule = angular.module('myModule',[])
myModule.controller('MyCtrl',['$scope',MyCtrl])
5、使用 controller as 語法:
<div ng-controller="MainCtrl as main">
{{ main.title }}
</div>
app.controller('MainCtrl', MainCtrl);
function MainCtrl () {
this.title = 'Some title';
}
使用 controller as 主要的優(yōu)點(diǎn)是:
- 創(chuàng)建了一個(gè)“獨(dú)立”的組件——綁定的屬性不屬于
$scope原型鏈。 - Scope值的改變會(huì)在你不注意的地方有影響。
- 難以重構(gòu)。
- 語法上更接近于普通的 JavaScript 構(gòu)造函數(shù)。
請(qǐng)看: digging-into-angulars-controller-as-syntax
6、不要在控制器中寫業(yè)務(wù)邏輯,業(yè)務(wù)邏輯交給模型層的服務(wù)。
// 這是把業(yè)務(wù)邏輯放在控制器的常見做法
angular.module('Store', [])
.controller('OrderCtrl', function ($scope) {
$scope.items = [];
$scope.addToOrder = function (item) {
$scope.items.push(item);//-->控制器中的業(yè)務(wù)邏輯
};
$scope.removeFromOrder = function (item) {
$scope.items.splice($scope.items.indexOf(item), 1);//-->控制器中的業(yè)務(wù)邏輯
};
$scope.totalPrice = function () {
return $scope.items.reduce(function (memo, item) {
return memo + (item.qty * item.price);//-->控制器中的業(yè)務(wù)邏輯
}, 0);
};
});
當(dāng)你把業(yè)務(wù)邏輯交給模型層的服務(wù),控制器看起來就會(huì)想這樣:(關(guān)于 service-model 的實(shí)現(xiàn),參看 'use services as your Model'):
// Order 在此作為一個(gè) 'model'
angular.module('Store', [])
.controller('OrderCtrl', function (Order) {
$scope.items = Order.items;
$scope.addToOrder = function (item) {
Order.addToOrder(item);
};
$scope.removeFromOrder = function (item) {
Order.removeFromOrder(item);
};
$scope.totalPrice = function () {
return Order.total();
};
});
為什么控制器不應(yīng)該包含業(yè)務(wù)邏輯和應(yīng)用狀態(tài)?
①控制器會(huì)在每個(gè)視圖中被實(shí)例化,在視圖被銷毀時(shí)也要同時(shí)銷毀
②控制器是不可重用的——它與視圖有耦合
③Controllers are not meant to be injected
7、有內(nèi)嵌的控制器時(shí)使用 "內(nèi)嵌作用域" ( controllerAs 語法):
app.js
module.config(function ($routeProvider) {
$routeProvider
.when('/route', {
templateUrl: 'partials/template.html',
controller: 'HomeCtrl',
controllerAs: 'home'
});
});
HomeCtrl
function HomeCtrl() {
this.bindingValue = 42;
}
template.html
<div ng-bind="home.bindingValue"></div>
四 模板
1、避免在模板中使用復(fù)雜的表達(dá)式。
2、當(dāng)需要?jiǎng)討B(tài)設(shè)置 的 src 時(shí)使用ng-src而非 src中嵌套 {{}} 的模板。href同理。
3、通過 ng-style 指令配合對(duì)象式參數(shù)和scope變量來動(dòng)態(tài)設(shè)置元素樣式,而不是將 scope變量作為字符串通過 {{ }} 用于 style 屬性。
<script>
...
$scope.divStyle = {
width: 200,
position: 'relative'
};
...
</script>
<div ng-style="divStyle">hello world</div>;
4、添加元素樣式
$scope.a=true;
$scope.b=false;
<div ng-class="{'red':a,'blue':b}"></div>
$scope.blnfocus=true;
<div ng-class="{true:'red',false:'blue'}[blnfocus]"></div>
列表中還有ng-class-odd 和 ng-class-even
簡(jiǎn)單例子:
<li ng-repeat="stu in data"
ng-click="li_click($index)"
ng-class-odd="odd"
ng-class-even="even"
ng-class="{focus:$index===focus}"
>
<span>{{stu.name}}</span>
<span>{{$first?'是':'否'}}</span>
<span>{{$last?'是':'否'}}</span>
</li>
$scope.li_click = function (i) {
$scope.focus = i;
}
css中需要加入.odd .even .focus
5、元素顯示隱藏ng-show ng-hide ng-switch(ng-switch-when ng-switch-default)
五 過濾器
1、orderby
<li ng-repeat="stu in data|orderBy:'-score'|limitTo:3">
按分?jǐn)?shù)降序排列,只顯示3條
2、匹配方式過濾filter
{{數(shù)據(jù)|filter:匹配項(xiàng)}}
匹配項(xiàng)可以是字符串、對(duì)象和函數(shù)
<li ng-repeat="stu in data|filter:findscore">
$scope.findscore = function (e){
return e.score>85 && e.score<90;
}
3、在需要格式化數(shù)據(jù)時(shí)將格式化邏輯封裝成 過濾器 并將其聲明為依賴
自定義過濾器
<li ng-repeat="stu in data|young:0">
module.filter('young',function(){
return function (e,type) {
var _out = [];
var _sex = type ? "男":"女";
for (var i = 0;i<e.length;i++) {
if (e[i].age > 22 && e[i].age<28 && e[i].sex == _sex)
_out.push(e[i]);
}
return _out;
}
})
在controller中注入自定義的filter
function MyCtrl($scope, young){
}
module.controller('MyCtrl', MyCtrl);
4、重要應(yīng)用
①表頭排序
<li >
<span ng-click="title='name';desc=!=desc">姓名</span>
<span ng-click="title='score';desc=!=desc">分?jǐn)?shù)</span>
</li>
<li ng-repeat="stu in data">
<span>{{stu.name}}</span>
<span>{{stu.score}}</span>
</li>
$score.title = 'name'
$score.desc = 0
②字符查找
<input type="text" ng-model="key">
<li ng-repeat="stu in data | filter:{name:key}">
<span>{{stu.name}}</span>
<span>{{stu.score}}</span>
</li>
六 作用域
作用域是控制器與視圖的橋梁,也是指令與視圖的橋梁
1、提供$watch方面監(jiān)聽數(shù)據(jù)模型變化(ng-model雙向綁定)
<input type="text" ng-model="key">
$scope.$watch('key',function(){
//...
})
2、子級(jí)可繼承父級(jí)作用域全部屬性和方法
同級(jí)不可以相互訪問屬性和方法
3、兩種方式實(shí)現(xiàn)作用域通信
①在作用域間創(chuàng)建一個(gè)單例的服務(wù)
②事件:只能父子相傳,同級(jí)接受不到
$broadcasted(eventname,data) 父到子
$emitted(eventname,data) 子到父
$on(eventname,function(event,data)){
//
}
在作用域監(jiān)聽傳播來的事件并獲取相應(yīng)的數(shù)據(jù)
七 依賴注入
1、當(dāng)在代碼中聲明了依賴關(guān)系后,Angular通過injector注入器將所依賴的對(duì)象進(jìn)行"注入"操作
2、config函數(shù)為定義的模板對(duì)象注入依賴的各種服務(wù),除了用于注冊(cè)控制器的controllerProvider服務(wù)外,還有provide服務(wù),它包含了幾個(gè)重要方法provider,factory,service,value
3、依賴注入標(biāo)記
①標(biāo)記式注入
調(diào)用$injector屬性來完成,字符型數(shù)組,一定要按注入方式的順序來
var MyCtrl = function($scope,$window,$show);
MyCtrl.$inject=[$scope,$window,$show]
②行內(nèi)式注入
將一個(gè)字符型數(shù)組作為對(duì)象參數(shù),最后一個(gè)是函數(shù)體,其余是注入對(duì)象中的服務(wù)名,它們順序與函數(shù)體參數(shù)一一對(duì)應(yīng)
module.controller('MyCtrl',[$scope,$window,function($scope,$window){
// ...
}])
4、依賴注入應(yīng)用場(chǎng)景
①構(gòu)建控制器:上述標(biāo)記式注入
②工廠方法:類似'config','factory','directive','filter'等構(gòu)造性質(zhì)的方法
八 angular服務(wù)
1、內(nèi)置服務(wù):$scope,$http,$window,$location
2、創(chuàng)建angular服務(wù),除了調(diào)用$provide服務(wù),還可以直接調(diào)用模塊中的factory、service、constant和value等方法來創(chuàng)建。
3、把業(yè)務(wù)邏輯封裝到服務(wù)中,把業(yè)務(wù)邏輯抽象為服務(wù)作為你的model。例如:
//Order is the 'model'
angular.module('Store')
.factory('Order', function () {
var add = function (item) {
this.items.push (item);
};
var remove = function (item) {
if (this.items.indexOf(item) > -1) {
this.items.splice(this.items.indexOf(item), 1);
}
};
var total = function () {
return this.items.reduce(function (memo, item) {
return memo + (item.qty * item.price);
}, 0);
};
return {
items: [],
addToOrder: add,
removeFromOrder: remove,
totalPrice: total
};
});
如果需要例子展現(xiàn)如何在控制器中使用服務(wù),請(qǐng)參考 'Avoid writing business logic inside controllers'。
九 使用promise而非回調(diào)
1、處理異步編程的模式,可以有效解決回調(diào)的繁瑣,以一種同步的方式去處理業(yè)務(wù)邏輯。
2、想要在angular中創(chuàng)建promise對(duì)象,必須在模板中注入$q服務(wù),并先調(diào)用defer方法創(chuàng)建一個(gè)延期對(duì)象。
var defer = $q.defer()
defer是一個(gè)延期對(duì)象,它包含3個(gè)方法notify、resolve、reject和promise對(duì)象
promise對(duì)象有一個(gè)then方法
promise.then(successCallback,errorCallback,notifyCallback)
3、實(shí)例
module.factory("async",function($q,$http){
var defer = $q.defer();
$http.get('data/asycn')
.success(function(data){
defer.resolve(data);
})
.error(function(reason){
defer.reject(reason) ;
})
return defer.promise;
})
.controller("MyCtrl",function($scope,async){
var promise = async;
promise.then(function(resp){
$scope.result = "成功"+resp;
},function(n){
$scope.result = "失敗"+n;
})
})
十 注意事項(xiàng)
1、調(diào)用element方法控制dom元素
angular.element(document.getElementById("control")).append(newhtml)
2、setTimeout無效,調(diào)用$timeout服務(wù)
在angular中,大部分操作之后的效果都是由$apply方法自動(dòng)在頁面完成,若調(diào)用非angular中方法,系統(tǒng)不會(huì)調(diào)用$apply方法在頁面中同步操作結(jié)果
3、{{}}閃爍問題
使用ng-bind ng-cloak
<div ng-cloak>{{message}}</div>
4、使用track by排序ng-repeat中的數(shù)據(jù)
5、釋放多余的$watch檢測(cè)函數(shù),再次調(diào)用$watch就可釋放它的檢測(cè)功能
$scope.stopWatch = function() {
contentWatch();
}
var contentWatch = $scope.$watch('content',function(newVal,oldVal){
if(newVal===oldVal){return;}
$scope.count++;
})
6、ng-if中ng-model值無效
<div ng-if="!a">
<input type="checkbox" ng-model="$parent.b">
</div>
參考:https://github.com/mgechev/angularjs-style-guide/blob/master/README-zh-cn.md
angularjs實(shí)戰(zhàn)