angularjs實際項目開發

最近看了看angularjs,這裏記錄下,怕自己忘記。

目錄

目錄架構

路由ui-router

簡介:

實例:

架構:

自定義服務

Factory:

5種其他創建方式

Service方式:

架構:

控制器

簡介:

實例:

架構:

自定義指令

directive

需要的設置項

常用參數介紹

controller:

作用域:

架構:

過濾器

模板使用:

Js調用:

自定義過濾器:

架構:

表單驗證

攔截器


 

實際開發

 

目錄架構

Angularjs也是延用了類似mvc的項目結構,view(html頁面和模板),controller(js中的控制器模塊),service(js中的服務),項目大體結構如下:

1.   controllers該模塊(文件夾)下都是項目的controller,作用是將view和service進行綁定與顯示。

2.   services該模塊(文件夾)下,與服務端接口對接,獲取數據。

3.   xxx.html項目的入口文件,裏面是所有js、controller、service等彙總文件

4.   xxx.js全局js文件,與路由、攔截器等相關。

5.   filters該模塊(文件夾)下,是定義的過濾器(一般是自定義)

6.   directives該模塊(文件夾)下,是自定義的指令

路由ui-router

簡介:

AngularUI庫提供的最有用的庫之一便是ui-router。angular-ui-router.js它是一個路由框架,允許你通過狀態機
組織接口,而不是簡單的URL路由。

 

1.   首先要引用該模塊:

 

 

2.   路由要在其他模塊開始前執行,在angular的config中進行配置,路由在控制器之上進行。

3.   默認路由

 

 

4.    $stateProvider中的state屬性的第一個參數

 

 

 

5.   templateUrl屬性獲取外部模板,main.tpl是外部的html模板

 

 

6.   controller屬性

第一種方式:

 

 

第二種方式:

 

 

7.   在控制器和指令中進行路由跳轉

 

 

點擊去首頁這個超鏈接,啓動to方法,便可到達下面路由,並找到對應內容

 

8.   路由參數設置和$stateParams服務

 

 

 

 

9.   路由定義父子級嵌套

  第一種方式:

Parent屬性指定父級路由,子路由中的模板會在父路由的模板中的view視圖下進行顯示。

 

 

第二種方式:在子路由前加上父路由

 

 

 

 

10.多路由嵌套

如果頁面是下面這種佈局,常見的路由用法:

 

 

 

 

三個ui-view視圖,下面state屬性裏用views進行多個嵌套,裏面可以加templateUrl、controller等屬性

 

 

 

點擊視頻超鏈接跳轉video路由,此時之將right.tpl進行替換

 

 

11.多路由父子嵌套

 

 

 

 

 

 

實例:

<html>

 <head>  

   <title>ui-router</title>

 

   <script type="text/javascript"src="angular.js"></script>

   <script type="text/javascript"src="angular-ui-router.js"></script> 

 </head>

 

 <body >  

   <div ng-app="myApp">       

       <div ui-view></div> <!-- 視圖 -->    

   </div> 

 </body>

 

 

 <script type="text/javascript">

   //定義模板,並注入ui-router

   var app = angular.module('myApp', ['ui.router']);  

   //對服務進行參數初始化,這裏配stateProvider服務的視圖控制

   app.config(["$stateProvider",'$urlRouterProvider',  function ($stateProvider,$urlRouterProvider){     

                   $urlRouterProvider.otherwise('/nv');

       $stateProvider

                   .state("home2",{

           url: '/default',  

           template:'<div>ss......</div>'

       })

                   .state("home3",{

           url: '/nv',  

           template:'<div>nv......</div>'

       })

                   .state("home",{

           url: '/main',  

           templateUrl:'main.tpl'

       })

                           

   }]); 

        

 

 </script>

 

</html>

 

架構:

 

我們將路由放入一個類似XXX router.js中,並進行引用.

自定義服務

Factory:

 

使用angular.module的factory API創建服務,是最常見也是最靈活的方式:
angular.module('myApp.services', [])
.factory('githubService', function() {
var serviceInstance = {};
// 我們的第一個服務
return serviceInstance;
});

 

5種其他創建方式

在AngularJS應用中, factory()方法是用來註冊服務的最常規方式,同時還有其他一些API
可以在特定情況下幫助我們減少代碼量。
共有5種方法用來創建服務:
qfactory()
qservice()
qconstant()
qvalue()
qprovider()

 

Service方式:

 

 

架構:

我們將自定義服務放入一個類似XXXService.js中,並進行引用。可以設計成總的指令js,也可以每個模塊寫一個js並放在servicess文件夾下

控制器

簡介:

除了孤立作用域外,所有的作用域都通過原型繼承而來,也就是說它們都可以訪問父級作用
域。如果熟悉面向對象編程,對這個機制應該不會陌生。
默認情況下, AngularJS在當前作用域中無法找到某個屬性時,便會在父級作用域中進行查
找。如果AngularJS找不到對應的屬性,會順着父級作用域一直向上尋找,直到抵達$rootScope
爲止。如果在$rootScope中也找不到,程序會繼續運行,但視圖無法更新。
通過例子來看一下這個行爲。創建一個ParentController,其中包含一個user對象,再創
建一個ChildController來引用這個對象:
app.controller('ParentController', function($scope) {
$scope.person = {greeted: false};
});
app.controller('ChildController', function($scope) {
$scope.sayHello = function() {
$scope.person.name = 'Ari Lerner';
};
});
如果我們將ChildController置於ParentController內部,那ChildController的$scope
對象的父級作用域就是ParentController的$scope對象。根據原型繼承的機制,我們可以在子
作用域中訪問ParentController的$scope對象

實例:

varapp = angular.module('app', []);
app.controller('FirstController', function($scope) {
$scope.message = "hello";
});

架構:

我們將自定義控制器放入一個類似XXXController.js中,並進行引用。可以設計成總的指令js,也可以每個模塊寫一個js並放在controllers文件夾下

 

自定義指令

directive

directive()這個方法是用來定義指令的可以接受兩個參數1. name(字符串)2. factory_function (函數)

angular.application('myApp',[])
.directive('myDirective', function() {
// 一個指令定義對象
return {
// 通過設置項來定義指令,在這裏進行覆寫
};
});

 

需要的設置項

可能的選項如下所示,每個鍵的值說明了可以將這個屬性設置爲何種類型或者什麼樣的
函數:
angular.module('myApp', [])
.directive('myDirective', function() {
return {
restrict: String,
priority: Number,
terminal: Boolean,
template: String or Template Function:
function(tElement, tAttrs) (...},
templateUrl: String,
replace: Boolean or String,
scope: Boolean or Object,
transclude: Boolean,
controller: String or
function(scope, element, attrs, transclude, otherInjectables) { ... },
controllerAs: String,
require: String,
link: function(scope, iElement, iAttrs) { ... },
compile: // 返回一個對象或連接函數,如下所示:
function(tElement, tAttrs, transclude) {
return {
pre: function(scope, iElement, iAttrs, controller) { ... },
post: function(scope, iElement, iAttrs, controller) { ... }
}
// 或者
return function postLink(...) { ... }

}
};
});

 

常用參數介紹

restrict是一個可選的參數。它告訴AngularJS這個指令在DOM中可以何種形式被聲明。默
認AngularJS認爲restrict的值是A,即以屬性的形式來進行聲明。
可選值如下:
E(元素)
<my-directive></my-directive>
A(屬性,默認值)
<div my-directive="expression"></div>
C(類名)
<div class="my-directive:expression;"></div>
M(註釋)
<--directive:my-directive expression-->
這些選項可以單獨使用,也可以混合在一起使用:
angular.module('myDirective', function(){
return {
restrict: 'EA' // 輸入元素或屬性
};
});
上面的配置可以同時用屬性或註釋的方式來聲明指令:
<-- 作爲一個屬性 -->
<div my-directive></div>
<-- 或者作爲一個元素 -->
<my-directive></my-directive>

 

 

template參數是可選的,必須被設置爲以下兩種形式之一:
q 一段HTML文本;
q 一個可以接受兩個參數的函數,參數爲tElement和tAttrs,並返回一個代表模板的字符
串。 tElement和tAttrs中的t代表template,是相對於instance的。在討論鏈接和編譯
設置時會詳細介紹,模板元素或屬性與實例元素或屬性之間的區別。
AngularJS會同處理HTML一樣處理模板字符串。模板中可以通過大括號標記來訪問作用域,
例如{{ expression }}。
如果模板字符串中含有多個DOM元素,或者只由一個單獨的文本節點構成,那它必須被包
含在一個父元素內。換句話說,必須存在一個根DOM元素:
template: '\
<div> <-- single root element -->\
<a href="http://google.com">Click me</a>\
<h1>When using two elements, wrap them in a parent element</h1>\
</div>\
另外,注意每一行末尾的反斜線,這樣AngularJS才能正確解析多行字符串。在實際生產中,
更好的選擇是使用templateUrl參數引用外部模板

 

 

templateUrl是可選的參數,可以是以下類型:
q 一個代表外部HTML文件路徑的字符串;
q 一個可以接受兩個參數的函數,參數爲tElement和tAttrs,並返回一個外部HTML文件
路徑的字符串。

 

replace是一個可選參數,如果設置了這個參數,值必須爲true,因爲默認值爲false。默
認值意味着模板會被當作子元素插入到調用此指令的元素內部:
<div some-directive></div>
.directive('someDirective', function() {
return {
template: '<div>some stuff here<div>'
};
});
調用指令之後的結果如下(這是默認replace爲false時的情況):
<div some-directive>
<div>some stuff here<div>
</div>
如果replace被設置爲了true:
.directive('someDirective', function() {
return {
replace: true // 修飾過
template: '<div>some stuff here<div>'
};
});
指令調用後的結果將是:
<div>some stuff here<div>。

 

 

transclude是一個可選的參數。如果設置了,其值必須爲true,它的默認值是false;將transclude設爲true後,在模板中加指令ng-transclude,頁面上原內容將放入指令的標籤中。

transclude:true,
template: '<div class="sidebox">\
<div class="content">\
<h2 class="header">{{ title }}</h2>\
<span class="content" ng-transclude>\
</span>\
</div>\
</div>'
};

 

controller:

controller參數可以是一個字符串或一個函數。當設置爲字符串時,會以字符串的值爲名字,
來查找註冊在應用中的控制器的構造函數:
angular.module('myApp', [])
.directive('myDirective', function() {
restrict: 'A', // 始終需要
controller: 'SomeController'
})
// 應用中其他的地方,可以是同一個文件或被index.html包含的另一個文件
angular.module('myApp')
.controller('SomeController', function($scope, $element, $attrs, $transclude) {
// 控制器邏輯放在這裏
});
可以在指令內部通過匿名構造函數的方式來定義一個內聯的控制器:
angular.module('myApp',[])
.directive('myDirective', function() {
restrict: 'A',
controller:
function($scope, $element, $attrs, $transclude) {
// 控制器邏輯放在這裏
}
});
我們可以將任意可以被注入的AngularJS服務傳遞給控制器。例如,如果我們想要將$log服
務傳入控制器,只需簡單地將它注入到控制器中,便可以在指令中使用它了。
控制器中也有一些特殊的服務可以被注入到指令當中。這些服務有:
1. $scope
與指令元素相關聯的當前作用域。
2. $element
當前指令對應的元素。
3. $attrs
由當前元素的屬性組成的對象。例如,下面的元素:
<div id="aDiv"class="box"></div>
具有如下的屬性對象:
{
id: "aDiv",
class: "box"
}

4.$transclude
嵌入鏈接函數會與對應的嵌入作用域進行預綁定。
transclude鏈接函數是實際被執行用來克隆元素和操作DOM的函數。

作用域:

 

控制器中作用域關係:

除了孤立作用域外,所有的作用域都通過原型繼承而來,也就是說它們都可以訪問父級作用
域。

默認情況下, AngularJS在當前作用域中無法找到某個屬性時,便會在父級作用域中進行查
找。如果AngularJS找不到對應的屬性,會順着父級作用域一直向上尋找,直到抵達$rootScope
爲止。如果在$rootScope中也找不到,程序會繼續運行,但視圖無法更新。

利用屬性的形式是繼承隔離,

利用對象的形式是繼承不隔離

1.   如果子作用域未自己定義屬性,都是繼承父作用域,則:父作用域屬性改變,子作用域屬性也會改變;子作用域屬性改變,父作用域屬性不改變。

2.   如果子作用域自己定義了屬性,則:父作用域屬性改變,子作用域屬性不會改變;子作用域屬性改變,父作用域屬性不改變;即父作用域和子作用域只改變自己;

3.   利用js對象傳值屬性,在父作用域與定義對象及其屬性,子作用域未自己定義屬性,都是繼承父作用域,則:父作用域屬性改變,子作用域屬性也會改變;子作用域屬性改變,父作用域屬性也改變。

 

 

4.   利用js對象傳值屬性,在父作用域與定義對象及其屬性,子作用域繼承對象並在對象中定義自己的屬性,則:父作用域屬性改變,子作用域屬性不會改變;子作用域屬性改變,父作用域屬性不改變。

 

指令中作用域的關係:

Directive中的scope屬性設置作用域的關係

1.   scope爲false時:這也是默認行爲,指令中的作用域和控制器中作用域完全共享數據,即控制器中作用域編號,指令中作用域也變化;指令中作用域變化,控制器中也變化。

2.   scope爲true時:類似繼承行爲,及指令中作用域繼承控制器中的作用域,具體看控制器中作用域關係中1、2兩點。

3.   scope爲{ }時:完全隔離,即控制器作用域和指令作用域之間數據隔離,指令和指令作用域之間也數據隔離。

 

@:單項數據綁定,父影響子

 

=:雙向數據綁定,父影響子,子影響父

 

&:調用父作用域方法

 

架構:

我們將自定義指令放入一個類似XXX Directive.js中,並進行引用。可以設計成總的指令js,也可以每個模塊寫一個js並放在directives文件夾下;restrict:'EA' // 一般用AE,templateUrl一般是指定外部模板

 

過濾器

AngularJS有很多實用的內置過濾器,同時也提供了方便的途徑可以自己創建過濾器。

模板使用:

在HTML中的模板綁定符號{{ }}內通過|符號來調用過濾器,例如:

<!--顯示: 123.46 -->
{{ 123.456789 | number:2 }}

Js調用:

在js代碼中可以通過$filter來調用過濾器。例如,在js代碼中使用lowercase
過濾器:
app.controller('DemoController', ['$scope', '$filter',
function($scope, $filter) {
$scope.name = $filter('lowercase')('Ari');
}]);

 

 

 

 

自定義過濾器:

過濾器本質上是一個會把我們輸入的內容當作參數傳入進去的函數。
angular.module('myApp.filters', [])
.filter('capitalize',function() {
return function(input) {
// input是我們傳入的字符串
if (input) {
return input[0].toUpperCase() + input.slice(1);
}
});
現在,如果想將一個句子的首字母轉換成大寫形式,可以用過濾器先將整個句子都轉換成小
寫,再把首字母轉換成大寫:
<!-- Ginger loves dog treats -->
{{ 'ginger loves dog treats' | lowercase | capitalize }}

 

架構:

我們將自定義過濾器放入一個類似XXXfilter.js中,並進行引用。可以設計成總的過濾器js,也可以每個模塊寫一個js並放在filters文件夾下。

 

表單驗證

Angular中新增了一個ngMessages指令,angular-messages.js,還要告訴Angular將ngMessages作爲應用程序的依賴模塊引入,就像這樣:
angular.module('myApp', ['ngMessages']);

 

<formname="signup_form" novalidate ng-submit="signupForm()"
ng-controller="signupController">

<label>Yourname</label>
<input type="text" placeholder="Name"name="name" ng-model="signup.name" ng-minlength=
3 ng-maxlength=20 required />
<div class="error"ng-messages="signup_form.name.$error">
<div ng-message="required">Make sure you enter yourname</div>
<div ng-message="minlength">Your name must be at least 3characters</div>
<div ng-message="maxlength">Your name cannot be longer than 20characters</div>
</div>
<button type="submit">Submit</button>
</form>

攔截器

攔截器的核心是服務工廠,通過向$httpProvider.interceptors數組中添加服務工廠,在$httpProvider中進行註冊。

一共有四種攔截器,兩種成功攔截器,兩種失敗攔截器。

request
AngularJS通過$http設置對象來對請求攔截器進行調用。它可以對設置對象進行修改,或者創建
一個新的設置對象,它需要返回一個更新過的設置對象,或者一個可以返回新的設置對象的promise。
q response
AngularJS通過$http設置對象來對響應攔截器進行調用。它可以對響應進行修改,或者創建
一個新的響應,它需要返回一個更新過的響應,或者一個可以返回新響應的promise。
q requestError
AngularJS會在上一個請求攔截器拋出錯誤,或者promise被reject時調用此攔截器。
qresponseError
AngularJS會在上一個響應攔截器拋出錯誤,或者promise被reject時調用此攔截器。

調用模塊的.factory()方法來創建攔截器,可以在服務中添加一種或多種攔截器:
angular.module('myApp', [])
.factory('myInterceptor', function($q) {
var interceptor = {
'request': function(config) {
// 成功的請求方法
return config; // 或者 $q.when(config);
},
'response': function(response) {
// 響應成功
return response; // 或者 $q.when(config);
},
'requestError': function(rejection) {
// 請求發生了錯誤,如果能從錯誤中恢復,可以返回一個新的請求或promise
return response; // 或新的promise
// 或者,可以通過返回一個rejection來阻止下一步
// return $q.reject(rejection);
},
'responseError': function(rejection) {
// 請求發生了錯誤,如果能從錯誤中恢復,可以返回一個新的響應或promise
return rejection; // 或新的promise
// 或者,可以通過返回一個rejection來阻止下一步
// return $q.reject(rejection);
}
};
return interceptor;
});
我們需要使用$httpProvider在.config()函數中註冊攔截器:
angular.module('myApp', [])
.config(function($httpProvider) {
$httpProvider.interceptors.push('myInterceptor');
});

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章