angular指令(二)--內置指令
一、基礎ng 屬性指令:
? ng-href
? ng-src
? ng-disabled
? ng-checked
? ng-readonly
? ng-selected
? ng-class
? ng-style
布爾屬性的有:
ng-disabled、ng-readonly、ng-checked、ng-selected
類布爾屬性有:
ng-href、ng-src
二、在指令中使用子作用域
? ng-app
? ng-controller
? ng-include
使用ng-include可以加載、編譯並包含外部HTML片段到當前的應用中。模板的URL被限制
在與應用文檔相同的域和協議下,可以通過白名單或包裝成被信任的值來突破限制。更進一步,
需要考慮跨域資源共享(Cross-Origin Resource Sharing,CORS)和同源規則(Same Origin Policy)
來確保模板可以在任何瀏覽器中正常加載。例如,所有瀏覽器都不能進行跨域的請求,部分瀏覽
器也不能訪問file://協議的資源。
在開發中,可以通過命令行命令chrome --allow-file-access-from-files來
禁止CORS錯誤。只在緊急情況下使用這個方法,比如你的老板正站在你身後,
並且所有事情都無法正常工作。
在同一個元素上添加onload屬性可以在模板加載完成後執行一個表達式。
要記住,使用ng-include時AngularJS會自動創建一個子作用域。如果你想使用某個特定的作
用域,例如ControllerA的作用域,必須在同一個DOM元素上添加ng-controller ="ControllerA"
指令,這樣當模板加載完成後,不會像往常一樣從外部作用域繼承並創建一個新的子作用域。下
面看一個例子:
<div ng-include="/myTemplateName.html" ng-controller="MyController" ng-init="name = ‘World‘"> Hello {{ name }} </div>
? ng-switch
這個指令和ng-switch-when及on="propertyName"一起使用,可以在propertyName發生變
化時渲染不同指令到視圖中。在下面的例子中,當person.name是Ari時,文本域下面的div會顯
示出來,並且這個人會獲得勝利:
<input type="text" ng-model="person.name"/> <div ng-switch on="person.name"> <p ng-switch-default>And the winner is</p> <h1 ng-switch-when="Ari">{{ person.name }}</h1> </div>
註意,在switch被調用之前我們用ng-switch-default來輸出默認值。
? ng-view
ng-view指令用來設置將被路由管理和放置在HTML中的視圖的位置。
? ng-if
使用ng-if指令可以完全根據表達式的值在DOM中生成或移除一個元素。如果賦值給ng-if
的表達式的值是false,那對應的元素將會從DOM中移除,否則對應元素的一個克隆將被重新插
入DOM中。
ng-if同no-show和ng-hide指令最本質的區別是,它不是通過CSS顯示或隱藏DOM節點,而
是真正生成或移除節點。
當一個元素被ng-if從DOM中移除,同它關聯的作用域也會被銷毀。而且當它重新加入DOM
中時,會通過原型繼承從它的父作用域生成一個新的作用域。
同時有一個重要的細節需要知道,ngIf重新創建元素時用的是它們編譯後的狀態。如果ng-if
內部的代碼加載之後被jQuery修改過(例如用.addClass),那麽當ng-if的表達式值為false時,
這個DOM元素會被移除,表達式再次成為true時這個元素及其內部的子元素會被重新插入
DOM,此時這些元素的狀態會是它們的原始狀態,而不是它們上次被移除時的狀態。也就是說
無論用jQuery的.addClass添加了什麽類都不會存在了。
<div ng-if="2+2===5"> Won‘t see this DOM node, not even in the source code </div> <div ng-if="2+2===4"> Hi, I do exist </div>
? ng-repeat
ng-repeat用來遍歷一個集合或為集合中的每個元素生成一個模板實例。集合中的每個元素
都會被賦予自己的模板和作用域。同時每個模板實例的作用域中都會暴露一些特殊的屬性。
? $index:遍歷的進度(0...length-1)。
? $first:當元素是遍歷的第一個時值為true。
? $middle:當元素處於第一個和最後元素之間時值為true。
? $last:當元素是遍歷的最後一個時值為true。
? $even:當$index值是偶數時值為true。
? $odd:當$index值是奇數時值為true。
下面的例子展示了如何用$odd和$even來制作一個紅藍相間的列表。記住,JavaScript中數組
的索引從0開始,因此我們用!$even和!$odd來將$even和$odd的布爾值反轉。
<ul ng-controller="PeopleController"> <li ng-repeat="person in people" ng-class="{even: !$even, odd: !$odd}"> {{person.name}} lives in {{person.city}} </li> </ul> .odd { background-color: blue; } .even { background-color: red; } angular.module(‘myApp‘,[]) .controller(‘PeopleController‘,function($scope) { $scope.people = [ {name: "Ari", city: "San Francisco"}, {name: "Erik", city: "Seattle"} ]; });
? ng-init
ng-init指令用來在指令被調用時設置內部作用域的初始狀態。
? ng-bind
盡管可以在視圖中使用{{ }}模板語法(AngularJS內置的方式),我們也可以通過ng-bind
指令實現同樣的行為。
<body ng-init="greeting=‘HelloWorld‘"> <p ng-bind="greeting"></p> </body>
HTML加載含有{{ }}語法的元素後並不會立刻渲染它們,導致未渲染內容閃爍(Flash of
Unrendered Content,FOUC)。我可以用ng-bind將內容同元素綁定在一起避免FOUC。內容會被
當作子文本節點渲染到含有ng-bind指令的元素內。
? ng-cloak
除使用ng-bind來避免未渲染元素閃爍,還可以在含有{{ }}的元素上使用ng-cloak指令:
<body ng-init="greeting=‘HelloWorld‘">
<p ng-cloak>{{ greeting }}</p>
</body>
ng-cloak指令會將內部元素隱藏,直到路由調用對應的頁面時才顯示出來。
? ng-bind-template
<div ng-bind-template="{{message}}{{name}}"> </div>
? ng-model
ng-model指令用來將input、select、text area或自定義表單控件同包含它們的作用域中
的屬性進行綁定。它可以提供並處理表單驗證功能,在元素上設置相關的CSS類(ng-valid、
ng-invalid等),並負責在父表單中註冊控件。
它將當前作用域中運算表達式的值同給定的元素進行綁定。如果屬性並不存在,它會隱式創
建並將其添加到當前作用域中。
我們應該始終用ngModel來綁定$scope上一個數據模型內的屬性,而不是$scope上的屬性,
這可以避免在作用域或後代作用域中發生屬性覆蓋。
例如:
<input type="text" ng-model="modelName.someProperty" />
? ng-show/ng-hide
ng-show和ng-hide根據所給表達式的值來顯示或隱藏HTML元素。當賦值給ng-show指令的
值為false時元素會被隱藏。類似地,當賦值給ng-hide指令的值為true時元素也會被隱藏。
元素的顯示或隱藏是通過移除或添加ng-hide這個CSS類來實現的。.ng-hide類被預先定義
在了AngularJS的CSS文件中,並且它的display屬性的值為none(用了!important標記)。
<div ng-show="2 + 2 == 5"> 2 + 2 isn‘t 5, don‘t show </div> <div ng-show="2 + 2 == 4"> 2 + 2 is 4, do show </div> <div ng-hide="2 + 2 == 5"> 2 + 2 isn‘t 5, don‘t hide </div> <div ng-hide="2 + 2 == 4"> 2 + 2 is 4, do hide </div>
? ng-change
這個指令會在表單輸入發生變化時計算給定表達式的值。因為要處理表單輸入,這個指令要
和ngModel聯合起來使用。
<div ng-controller="EquationController"> <input type="text" ng-model="equation.x" ng-change="change()" /> <code>{{ equation.output }}</code> </div> angular.module(‘myApp‘,[]) .controller(‘EquationController‘,function($scope) { $scope.equation = {}; $scope.change = function() { $scope.equation.output = parseInt($scope.equation.x) + 2; }; });
上面的例子中,只要文本輸入字段中的內容發生了變化就會改變equation.x的值,進而運
行change()函數。
? ng-form
ng-form用來在一個表單內部嵌套另一個表單。普通的HTML <form>標簽不允許嵌套,但
ng-form可以。
這意味著內部所有的子表單都合法時,外部的表單才會合法。這對於用ng-repeat動態創建
表單是非常有用的。
由於不能通過字符插值來給輸入元素動態地生成name屬性,所以需要將ng-form指令內每組
重復的輸入字段都包含在一個外部表單元素內。
下面的CSS類會根據表單的驗證狀態自動設置:
? 表單合法時設置ng-valid;
? 表單不合法時設置ng-invlid;
? 表單未進行修改時設置ng-pristion;
? 表單進行過修改時設置ng-dirty。
Angular不會將表單提交到服務器,除非它指定了action屬性。要指定提交表單時調用哪個
JavaScript方法,使用下面兩個指令中的一個。
? ng-submit:在表單元素上使用。
? ng-click:在第一個按鈕或submit類型(input[type=submit])的輸入字段上使用。
為了避免處理程序被多次調用,只使用下面兩個指令中的一個。
下面的例子展示了如何通過服務器返回的JSON數據動態生成一個表單。我們用ng-loop來遍
歷從服務器取回的所有數據。由於不能動態生成name屬性,而我們又需要這個屬性做驗證,所以
在循環的過程中會為每一個字段都生成一個新表單。
由於AngularJS中用來取代<form>的ng-form指令可以嵌套,並且外部表單在所有子表單都合
法之前一直處於不合法狀態,因此我們可以在動態生成子表單的同時使用表單驗證功能。是的,
魚和熊掌可以兼得。
下面先看一下我們硬編碼的JSON數據,把它假設成是從服務器返回的:
angular.module(‘myApp‘,[]) .controller(‘FormController‘,function($scope) { $scope.fields = [ {placeholder: ‘Username‘, isRequired: true}, {placeholder: ‘Password‘, isRequired: true}, {placeholder: ‘Email (optional)‘, isRequired: false} ]; $scope.submitForm = function() { alert("it works!"); }; });
下面用這些數據生成一個有驗證功能的動態表單:
<form name="signup_form" ng-controller="FormController" ng-submit="submitForm()" novalidate> <div ng-repeat="field in fields" ng-form="signup_form_input"> <input type="text" name="dynamic_input" ng-required="field.isRequired" ng-model="field.name" placeholder="{{field.placeholder}}" /> <div ng-show="signup_form_input.dynamic_input.$dirty && signup_form_input.dynamic_input.$invalid"> <span class="error" ng-show="signup_form_input.dynamic_input.$error.required"> The field is required. </span> </div> </div> <button type="submit" ng-disabled="signup_form.$invalid"> Submit All </button> </form> input.ng-invalid { border: 1px solid red; } input.ng-valid { border: 1px solid green; }
? ng-click
ng-click用來指定一個元素被點擊時調用的方法或表達式。
<div ng-controller="CounterController"> <button ng-click="count = count + 1" ng-init="count=0"> Increment </button> count: {{ count }} <button ng-click="decrement()"> Decrement </button> <div> angular.module(‘myApp‘,[]) .controller(‘CounterController‘, function($scope) { $scope.decrement = function() { $scope.count = $scope.count - 1; }; })
? ng-select
ng-select用來將數據同HTML的<select>元素進行綁定。這個指令可以和ng-model以及
ng-options指令一同使用,構建精細且表現優良的動態表單。
ng-options的值可以是一個內涵表達式(comprehension expression),其實這只是一種有趣
的說法,簡單來說就是它可以接受一個數組或對象,並對它們進行循環,將內部的內容提供給
select標簽內部的選項。它可以是下面兩種形式。
? 數組作為數據源:
? 用數組中的值做標簽;
? 用數組中的值作為選中的標簽;
? 用數組中的值做標簽組;
? 用數組中的值作為選中的標簽組。
? 對象作為數據源:
? 用對象的鍵?值(key-value)做標簽;
? 用對象的鍵?值作為選中的標簽;
? 用對象的鍵?值作為標簽組;
? 用對象的鍵?值作為選中的標簽組。
下面看一個ng-select指令的實例:
<div ng-controller="CityController"> <select ng-model="city" ng-options="city.name for city in cities"> <option value="">Choose City</option> </select> Best City: {{ city.name }} </div> angular.module(‘myApp‘,[]) .controller(‘CityController‘,function($scope) { $scope.cities = [ {name: ‘Seattle‘}, {name: ‘San Francisco‘}, {name: ‘Chicago‘}, {name: ‘New York‘}, {name: ‘Boston‘} ]; });
? ng-submit
ng-submit用來將表達式同onsubmit事件進行綁定。這個指令同時會阻止默認行為(發送請
求並重新加載頁面),除非表單不含有action屬性。
<form ng-submit="submit()" ng-controller="FormController"> Enter text and hit enter: <input type="text" ng-model="person.name" name="person.name" /> <input type="submit" name="person.name" value="Submit" /> <code>people={{people}}</code> <ul ng-repeat="(index, object) in people"> <li>{{ object.name }}</li> </ul> </form> angular.module(‘myApp‘,[]) .controller(‘FormController‘,function($scope) { $scope.person = { name: null }; $scope.people = []; $scope.submit = function() { if ($scope.person.name) { $scope.people.push({name: $scope.person.name}); $scope.person.name = ‘‘; } }; });
? ng-class
使用ng-class 動態設置元素的類,方法是綁定一個代表所有需要添加的類的表達式。重復
的類不會添加。當表達式發生變化,先前添加的類會被移除,新類會被添加。
下面的例子會用ng-class在一個隨機數大於5時將.red類添加到一個div上:
<div ng-controller="LotteryController"> <div ng-class="{red: x > 5}" ng-if="x > 5"> You won! </div> <button ng-click="x = generateNumber()" ng-init="x = 0"> Draw Number </button> <p>Number is: {{ x }}</p> </div> .red { background-color: red; } angular.module(‘myApp‘,[]) .controller(‘LotteryController‘, function($scope) { $scope.generateNumber = function() { return Math.floor((Math.random()*10)+1); }; });
? ng-attr-(suffix)
當AngularJS編譯DOM時會查找花括號{{ some expression }}內的表達式。這些表達式會
被自動註冊到$watch服務中並更新到$digest循環中,成為它的一部分:
<-- updated when`someExpression` on the$scope
is updated -->
<h1>Hello{{someExpression}}</h1>
有時瀏覽器會對屬性會進行很苛刻的限制。SVG就是一個例子:
<svg>
<circle cx="{{ cx }}"></circle>
</svg>
運行上面的代碼會拋出一個錯誤,指出我們有一個非法屬性。可以用ng-attr-cx來解決這
個問題。註意,cx位於這個名稱的尾部。在這個屬性中,通過用{{ }}來寫表達式,達到前面提
到的目的。
<svg>
<circle ng-attr-cx="{{ cx }}"><circle>
</svg>
angular指令(二)--內置指令