javascript
AngularJS学习笔记(一)
前言
幾個月之前了解過一點Angular,主要是通過phonecat應用程序了解一些入門東西,但是當被問及什么是Angular或者你對Angular的理解時,只記得一個MVVM雙向數據綁定,顯然這是不能令人滿意的?,F在重新來過吧。
ps:該文檔只是見證自己學習Angular的過程。所用版本為1.4.3。另外向大家推薦個windows下各 API離線查找工具Velocity,官網:http://velocity.silverlakesoftware.com/,真的不是一般地好用。
AngularJS簡介
AngularJS是一個為動態WEB應用設計的結構框架,創新點在于,利用數據綁定和依賴注入,使你不用再寫大量的代碼。AngularJS的一些出眾之處在于:
- 構建一個CRUD應用可能用到的全部內容包括:數據綁定、基本模板標識符、表單驗證、路由、深度鏈接、組件重用、依賴注入
- 測試方面包括:單元測試、端到端測試、模擬和自動化則是框架
- 具有目錄布局和測試腳本的種子應用作為起點
而Angular信奉的是,當組建視圖同時又要寫軟件邏輯時,聲明式的代碼會比命令式的代碼好的多。
基本概念
首先舉個例子:
<!doctype html> <html lang="en" ng-app="myApp"> <head><meta charset="UTF-8"><title>myApp</title><style>#test {width: 100px;height: 100px;background-color: red;border: 1px solid #ccc;}</style><script src="js/jquery-1.7.1.js"></script><script src="js/angular.min.js"></script> </head> <body ng-controller="myCtrl"><div id="test" ng-click="click()">Come ON!</div><p>{{width}} * {{height}}</p><p>Width: <input type="text" ng-model="width"/></p><p>Height: <input type="text" ng-model="height"/></p><script>"use strict";var myApp = angular.module("myApp", []);myApp.controller('myCtrl', ['$scope', function($scope) {var oDiv = angular.element('#test');$scope.width = oDiv.width();$scope.height = oDiv.height();$scope.click = function() {$scope.width = parseInt($scope.width) + 10;$scope.height = parseInt($scope.height) + 10;};$scope.$watch('width', function(to, from) {oDiv.width(to);});$scope.$watch('height', function(to, from) {oDiv.height(to);});}]);</script> </body> </html>從代碼中可以看出,在HTML中引入了一些以ng開頭的標記,這些就是angular(一下簡稱ng)聲明式的代碼。
- 使用ng-app聲明ng的初始化工作,同時定義了ng應用的作用域,ng的初始化一般綁定在DOMContentLoaded事件中,可以使用angular.bootstap(element,modules,config);手動引導ng應用程序。
- ng-controller聲明控制器,控制器里可以寫相應的代碼邏輯,修改相應的$scope,進行model到view的數據綁定工作。
- ng-click綁定click事件,事件在controller中聲明,綁定到$scope.
- ng模板解析:默認使用{{}}
- ng-model:ng的雙向數據綁定聲明
依賴注入
ng通過在函數參數中做手腳來完成“依賴聲明”的功能。['$scope', 'dep1', 'dep2', function($scope, dep1, dep2) {}]像AMD聲明一樣,該函數依賴于$scope,dep1,dep2,然后依次作為參數傳遞進去。也可以使用另外一種聲明方式,利用ng中的函數隱藏屬性$inject(不推薦):
var MyController = function($scope, greeter) {} MyController.$inject = ['$scope', 'greeter']; someModule.controller('MyController', MyController);在處理時,ng通過函數對象的toString()方法將該函數定義的代碼轉為字符串表現形式,然后利用正則表達式過濾出相應的參數,通過參數名獲取資源,最后把資源作為參數調用定義的函數。
因此最好采用上述兩種方法來顯示聲明所需的依賴,防止代碼壓縮過程中壓縮相應的函數參數而報錯。
作用域
每個ng應用都有一個根作用域($rootScope),有多個子作用域。因為一些指令會聲明新的子作用域,這些作用域的結構關系和其綁定到相應的DOM結構是對應的。
屬性查找:當ng查找某個模板中的某個數據時,會按照作用域鏈一直向上查找,直至找到或查至根作用域$rootrScope為至(獨立作用域除外)。
事件冒泡:我們可以在scopes上模擬DOM事件類型的事件冒泡,該事件可以被廣播到子作用域或者觸發到父作用域。
<div ng-controller="EventController">Root scope <tt>MyEvent</tt> count: {{count}}<ul><li ng-repeat="i in [1]" ng-controller="EventController"><button ng-click="$emit('MyEvent')">$emit('MyEvent')</button><button ng-click="$broadcast('MyEvent')">$broadcast('MyEvent')</button><br>Middle scope <tt>MyEvent</tt> count: {{count}}<ul><li ng-repeat="item in [1, 2]" ng-controller="EventController">Leaf scope <tt>MyEvent</tt> count: {{count}}</li></ul></li></ul> </div><script>angular.module('myApp', []).controller('EventController', ['$scope', function($scope) {$scope.count = 0;$scope.$on('MyEvent', function() {$scope.count++;});}]);</script>另外,我們還可以調用$watch()檢測某個屬性改變。
模板與數據綁定
ng中的主要特點之一就是雙向數據綁定。
數據->模板:
可以直接使用ng的默認模板標記{{name}},則可以直接綁定一個作用域內的變量。當然也可以更改使用自定義的標記//name//
<script>myApp.config(function($interpolateProvider) {$interpolateProvider.startSymbol('//');$interpolateProvider.endSymbol('//');}); </script>模板:
ng有自己的一套強大的模板命令:
1.ng-include直接引入模板內容
<div ng-include="'template.html'"></div>
ng-include內容必須是字符串,需多加個引號。
template.html主要有兩種定義方式:
(1)script標簽中定義:type屬性值為“text/ng-template”,id為ng-include屬性值
(2)外部html文件中定義:該html文件名為ng-include的屬性值
Content of template.html2.內容控制:
(1)ng-cloak
該指令綁定內容不顯示,直到ng解析相關指令后才顯示解析后的內容,避免相關內容解析前后出現跳轉現象。
(2)ng-show/ng-hide
根據表達式的值來改變綁定該命令的DOM的display屬性,相關CSS類已經在ng文件中提前定義,且使用了!important提升權重。
(3)ng-if
不同于ng-show改變DOM的display屬性來顯示隱藏節點,ng-if根據表達式的布爾值判斷:false則從文檔中移除該DOM節點,true則向文檔中添加該DOM節點。
(4)ng-switch
根據值的匹配情況來顯示相應的節點:
ng-init直接在模板中進行賦值,與作用域無關。
(5)ng-repeat
遍歷對象或數組:
額外變量:
$index 當前索引
$first 是否為首元素
$middle 是否為中間元素
$last 是否為尾元素
$odd 當前索引是否為奇數
$even 當前索引是否為偶數
遍歷對象使用(key, value) in obj.
另外,默認待遍歷的數組中不能有重復值,因為數組元素與相應的DOM元素是一對一的關系。如需要使用:
(6)其它
- ng-src src屬性
- ng-href href屬性
- ng-checked 選中狀態
- ng-selected 被選擇狀態
- ng-disabled 禁用狀態
- ng-multiple 多選狀態
- ng-readonly 只讀狀態
3.樣式
(1)ng-style
使用對象字面量的形式來賦值:
(2)ng-class
直接通過字符串綁定CSS中預定義的類
4.事件綁定:
模板中的事件綁定預定義了一些常用的事件綁定指令,可以直接傳遞相關的處理程序且直觀地在DOM中聲明。
- ng-blur
- ng-change
- ng-click
- ng-dblclick
- ng-focus
- ng-keydown
- ng-keypress
- ng-keyup
- ng-mousedown
- ng-mouseenter
- ng-mouseleave
- ng-mousemove
- ng-mouseover
- ng-mouseup
使用$event可以給相應的事件處理函數傳遞事件對象本身
5.表單
HTML中form是一個核心控件,是網頁與用戶進行交流的主要方式之一。而ng對form進行了封裝”ng-form”,區別是HTML中的form不能嵌套,而ng-form可以嵌套。而ng-form的目的就是為了統一控制,而不是為了取代form標簽。
form中的一些控件可以預先通過ng-controller中的$scope綁定一些狀態。
<!doctype html> <html lang="en" ng-app="myApp"> <head><meta charset="UTF-8"><title>Document</title><script src="js/angular.min.js"></script> </head> <script>angular.module('myApp', []).controller('FormController', ['$scope', function($scope) {$scope.userType = 'guest';}]); </script> <style>.my-form {-webkit-transition:all linear 0.5s;transition:all linear 0.5s;background: transparent;}.my-form.ng-invalid {background: red;} </style> <body> <form name="myForm" ng-controller="FormController" class="my-form">userType: <input name="input" ng-model="userType" required ><span class="error" ng-show="myForm.input.$error.required">Required!</span><br>age: <input name="input_b" ng-model="age" required pattern="\d+"><span class="error" ng-show="myForm.input_b.$error.required">Required!</span><span class="error" ng-show="myForm.input_b.$error.pattern">Pattern!</span><br><code>userType = {{userType}}</code><br><code>myForm.input.$valid = {{myForm.input.$valid}}</code><br><code>myForm.input.$error = {{myForm.input.$error}}</code><br><code>myForm.$valid = {{myForm.$valid}}</code><br><code>myForm.$error.required = {{!!myForm.$error.required}}</code><br> </form> </body> </html>ng給form提前定義了一些CSS類:
- ng-valid 當表單驗證全部通過時使用
- ng-invalid 表單中有未通過驗證的控件時使用
- ng-pristine 當表單為被修改之前使用
- ng-dirty 當表單被修改之后使用
- ng-submitted 當表單被提交之后使用
form對象有一些屬性:
- $pristine 表單是否未被動過
- $dirty 表單是否被動過
- $valid 表單是否通過驗證
- $invalid 表單是否未通過驗證
- $error 表單的錯誤對象
其中$error是一個hash對象,引用表單控件中未通過驗證的鍵值對。屬性是驗證失敗信息,值是對應的實例列表。另外,該失敗對象是按一定的驗證邏輯所取,例如上例中的age輸入框,先判定required,在判定pattern。$error對象可能的屬性有:email/max/maxlength/min/minlength/number/pattern/required/url/date/time/week/month.
同時,我們也能在form中的具體某個input框中查看相應的錯誤,格式為formName.inputName.$error.但是,input控件的相關屬性是ng-required/ng-pattern等,經測試發現,僅ng-maxlength,ng-max,ng-min與HTML5中相關屬性有區別:ng-maxlength=’12’可以輸入超過12個字符,但超過相關屬性為true,而maxlength則最多只能輸入12個字符,超過默認丟棄,相關錯誤屬性永不為true.
(1)checkbox/radio
可以為checkbox分別綁定ng-true-value/ng-false-value的值,為radio綁定value值。而這些值與視圖中的相關控件是否選中相對應。
(2)textarea
包含input框中相應屬性,僅多了ng-trim指令。
(3)select
select控件中,有個用于呈現下拉選項的指令ng-options主要用于select模板中綁定的是非字符串。主要用法見下例:
通常情況下,ng-repeat也可用在option元素中,但ng-repeat會為每個遍歷的實例創造一個新的作用域,而使用ng-options則具有節省內存,響應更快捷的優點。
模板->數據:
ng中模板到數據的綁定主要是通過ng-model來實現。
<p>hello {{name || "World"}}!</p> <hr/> <input type="text" ng-model="name"/>當我們在input框中輸入內容,會發現模板中內容也相應改變。實際上,ng中的雙向數據綁定主要是通過ng-model來實現。
過濾
ng默認提供了一些可以直接使用的過濾指令
- currency 貨幣過濾指令
- date 時間過濾指令
- filter 數組過濾指令
- json 將js對象轉換為json字符串
- limitTo 截取字符串/數組/數字的一部分
- lowercase 字符串轉小寫
- number 格式化數字
- orderBy 數組排序
- uppercase 字符串轉大寫
- linky 找出文本輸入中的連接然后格式化
模板中使用
我們可以在模板中使用過濾命令,使用方法類似與linux系統中的管道命令{{expression | filter1:arg1:arg2:... | filter2:arg}}即我們可以在一個語句后面使用多個過濾命令,依次用”|”分割開即可,也可以在一個過濾命令后面傳遞多個參數,依次用“:”分割開即可。
<span>{{1437272917693 | date:"MM/dd/yyyy 'at' h:mma"}}</span><br> <span>{{ ["AAAAA","AAAA","AAA","AA","A","BBB","BB"] | filter:'A' | limitTo: 2 }}</span><br>JS中使用
JS中使用過濾命令有兩種方式:
(1)<filterName>Filter方式:
在依賴聲明中明確聲明需要使用filterName的過濾指令,然后就可以在內部向該指令函數傳遞參數,返回處理后的數據:
(2)$filter方式
依賴聲明中引入$filter,然后我們就可以在內部向該函數傳入我們想要使用的過濾指令名,返回對應的過濾指令函數。較方式1簡單:
自定義過濾命令
如果感覺ng默認提供的幾種過濾指令滿足不了需求,我們可以自定義指令。通過你的module中的filter工廠函數就可以自定義一個新的指令。
angular.module('myApp', []).filter('reverse', function() {return function(input, uppercase) {input = input || '';var out = "";for (var i = 0; i < input.length; i++) {out = input.charAt(i) + out;}// 可傳入參數uppercaseif (uppercase) {out = out.toUpperCase();}return out;};})向filter工廠函數傳入命令名,初始化函數,返回一個過濾函數,過濾函數第一個參數是待過濾的內容,其余參數依次輸入。僅當該過濾指令的輸入內容改變時,ng才會執行該指令。
另外,自定義的過濾函數應該全部是無狀態的,那些有狀態的指令無法被ng優化,經常導致表現問題。而如果真的需要維持狀態的過濾命令,可指定該過濾函數的$stateful屬性,這樣每次模板中內容改變該過濾函數都會執行一次。
另外,自定義的過濾函數只能在模板中使用。
AJAX
與其它框架一樣,ng也提供了類似的一套AJAX封裝,內部通過XMLHttpRequest對象或JSONP方式。
$HTTP
$HTTP提供基本的操作服務,傳入一個config配置對象,設置一些參數,返回一個可以注冊成功、失敗回調函數的promise對象。$http常用的配置有:
- method 請求方法
- url 請求路徑
- params GET請求的參數
- data 請求報文(POST請求的參數)
- headers 定義請求報頭
- cache GET請求的緩存
- timeout 過期時間
- responseType 響應類型
另外對于一些請求方式,有一些簡寫:
- $http.get(url, [config])
- $http.delete(url, [config])
- $http.head(url, [config])
- $http.jsonp(url, [config])
- $http.post(url, data, [config])
- $http.put(url, data, [config])
$http屬性:
- pendingRequests 當前請求隊列狀態,主要用于測試
- defaults 請求的全局配置
異步回調
ng的異步回調函數服務$q為AJAX的異步回調提供服務。
(1)$q用法
- $q(resolveFn, errorFn) 注冊并返回一個promise對象
- $q.defer() 返回一個deferred實例
- $q.reject(reason) 包裝一個錯誤
- $q.when(value) 返回一個promise對象
- $q.resolve(value) 與when方法一樣,為了與ES6保持一致性
- $q.all(promises) 將多個promise對象合并成一個promise對象
(2)deferred對象:通過$q.defer()構建
- resolve(value) 成功回調
- reject(reason) 失敗回調
- notify(value) 更新promise的執行狀態
- promise屬性 返回一個promise對象
(3)promise
- then(successCallback, errorCallback, notifyCallback) 分別注冊成功,失敗,通知的回調函數
- catch(errorCallback) 相當于then(null, errorCallback) 注冊失敗回調函數
- finally(callback, notifyCallback)
其它部分,明天繼續。。。
參考內容
http://www.zouyesheng.com/angular.html
http://www.cnblogs.com/lcllao/archive/2012/10/18/2728787.html
轉載于:https://www.cnblogs.com/qingguo/p/5686290.html
總結
以上是生活随笔為你收集整理的AngularJS学习笔记(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么了解泰山的历史故事?
- 下一篇: 怎么在泰山保护自身安全?