解析最簡單的指令hello:匹配模式restrict
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
</head>
<body>
<hello></hello>
<div hello></div>
<div class="hello"></div>
<!-- directive:hello -->
<div></div>
</body>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="HelloAngular_Directive.js"></script>
</html>
var myModule = angular.module("MyModule", []);
myModule.directive("hello", function() {
return {
restrict: 'AEMC',
template: '<div>Hi everyone!</div>',
replace: true
}
});
restrict表示匹配模式
A表示屬性
E表示元素
M表示注釋
C表示樣式類
解析最簡單的指令hello:template找田,templateUrl仰坦,$templateCache
在上面最簡單的指令里面有一個配置項template這是最總要顯示的html標簽
使用這種方式編寫的內(nèi)容比較少箱吕,
AngularJS提供了templateUrl配置項右核,使用這個就不需要把模板寫道js代碼里面
把模板切成獨立的html去編寫,可以編寫很多內(nèi)容。
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
</head>
<body>
<hello></hello>
</body>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="templateUrl.js"></script>
</html>
var myModule = angular.module("MyModule", []);
myModule.directive("hello", function() {
return {
restrict: 'AECM',
templateUrl: 'hello.html',
replace: true
}
});
hello
<div class="panel panel-primary">
<div class="panel-heading">
<div class="panel-title">雙向數(shù)據(jù)綁定</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-12">
<form class="form-horizontal" role="form" ng-controller="UserInfoCtrl">
<div class="form-group">
<label class="col-md-2 control-label">
郵箱:
</label>
<div class="col-md-10">
<input type="email" class="form-control" placeholder="推薦使用126郵箱" ng-model="userInfo.email">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">
密碼:
</label>
<div class="col-md-10">
<input type="password" class="form-control" placeholder="只能是數(shù)字隧膏、字母、下劃線" ng-model="userInfo.password">
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="userInfo.autoLogin">自動登錄
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button class="btn btn-default" ng-click="getFormData()">獲取Form表單的值</button>
<button class="btn btn-default" ng-click="setFormData()">設置Form表單的值</button>
<button class="btn btn-default" ng-click="resetForm()">重置表單</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
</head>
<body>
<hello></hello>
</body>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="$templateCache.js"></script>
</html>
var myModule = angular.module("MyModule", []);
//注射器加載完所有模塊時嚷那,此方法執(zhí)行一次
myModule.run(function($templateCache){
$templateCache.put("hello.html","<div>Hello everyone!!!!!!</div>");
});
myModule.directive("hello", function($templateCache) {
return {
restrict: 'AECM',
template: $templateCache.get("hello.html"),
replace: true
}
});
$templateCache這個配置項是緩存的意思胞枕。
template: $templateCache.get("hello.html"),
就可以使用
也就是說將模板緩存起來去讓多個指令去使用他
解析最簡單的指令hello:replace與trabsclude
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
</head>
<body>
<hello>
<div>這里是指令內(nèi)部的內(nèi)容。</div>
</hello>
</body>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="replace.js"></script>
</html>
var myModule = angular.module("MyModule", []);
myModule.directive("hello", function() {
return {
restrict:"AE",
template:"<div>Hello everyone!</div>",
replace:true
}
});
hello作為一個元素當然是可以嵌套的魏宽,
如果使用replace配置項內(nèi)部寫的內(nèi)容就會被替換掉腐泻,
但是有一個div
<hello>
<div>這里是指令內(nèi)部的內(nèi)容。</div>
</hello>
使用trabsclude方式
trabsclude表示變換队询,
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
</head>
<body>
<hello>
<div>這里是指令內(nèi)部的內(nèi)容派桩。</div>
</hello>
</body>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="transclude.js"></script>
</html>
var myModule = angular.module("MyModule", []);
myModule.directive("hello", function() {
return {
restrict:"AE",
transclude:true,
template:"<div>Hello everyone!<div ng-transclude></div></div>"
}
});
使用trabsclude內(nèi)部嵌套的內(nèi)容會保存下來。這個有非常重要的作用蚌斩,因為指令互相之間是可以嵌套的铆惑,如果最外層的指令把內(nèi)部的內(nèi)容全部替換,很顯然內(nèi)部的指令沒有辦法起作用送膳。
comile與link(操作元素鸭津,添加css樣式,綁定事件)
指令在執(zhí)行時候的機制
指令與控制器之間的交互
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-controller="MyCtrl">
<loader howToLoad="loadData()">滑動加載</loader>
</div>
<div ng-controller="MyCtrl2">
<loader howToLoad="loadData2()">滑動加載</loader>
</div>
</body>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="Directive&Controller.js"></script>
</html>
var myModule = angular.module("MyModule", []);
myModule.controller('MyCtrl', ['$scope', function($scope){
$scope.loadData=function(){
console.log("加載數(shù)據(jù)中...");
}
}]);
myModule.controller('MyCtrl2', ['$scope', function($scope){
$scope.loadData2=function(){
console.log("加載數(shù)據(jù)中...22222");
}
}]);
myModule.directive("loader", function() {
return {
restrict:"AE",
link:function(scope,element,attrs){
element.bind('mouseenter', function(event) {
//scope.loadData();
// scope.$apply("loadData()");
// 注意這里的坑肠缨,howToLoad會被轉(zhuǎn)換成小寫的howtoload
scope.$apply(attrs.howtoload);
});
}
}
});
指令通過屬性值的不同來調(diào)用不同控制器上的方法
link:function(scope,element,attrs)
scope作用域
element元素
attrs屬性
指令間的交互
scope: {}, 創(chuàng)建獨立作用域scope
這里面的controller和MVC的controller不是一個東西逆趋,這個是指令內(nèi)部的controller,他是用來給我們的指令暴露出一組方法給外部去調(diào)用的晒奕。
supermanCtrl在link中
controller給指令暴露了三個方法
指令間的交互是通過指令上面內(nèi)部的controller暴露出來的方法來給外部進行調(diào)用的闻书,
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="Directive&Directive.js"></script>
</head>
<body>
<div class="row">
<div class="col-md-3">
<superman strength>動感超人---力量</superman>
</div>
</div>
<div class="row">
<div class="col-md-3">
<superman strength speed>動感超人2---力量+敏捷</superman>
</div>
</div>
<div class="row">
<div class="col-md-3">
<superman strength speed light>動感超人3---力量+敏捷+發(fā)光</superman>
</div>
</div>
</body>
</html>
var myModule = angular.module("MyModule", []);
myModule.directive("superman", function() {
return {
scope: {},
restrict: 'AE',
controller: function($scope) {
$scope.abilities = [];
this.addStrength = function() {
$scope.abilities.push("strength");
};
this.addSpeed = function() {
$scope.abilities.push("speed");
};
this.addLight = function() {
$scope.abilities.push("light");
};
},
link: function(scope, element, attrs) {
element.addClass('btn btn-primary');
element.bind("mouseenter", function() {
console.log(scope.abilities);
});
}
}
});
myModule.directive("strength", function() {
return {
require: '^superman',
link: function(scope, element, attrs, supermanCtrl) {
supermanCtrl.addStrength();
}
}
});
myModule.directive("speed", function() {
return {
require: '^superman',
link: function(scope, element, attrs, supermanCtrl) {
supermanCtrl.addSpeed();
}
}
});
myModule.directive("light", function() {
return {
require: '^superman',
link: function(scope, element, attrs, supermanCtrl) {
supermanCtrl.addLight();
}
}
});
scope的類型與獨立scope
什么是獨立scope
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
</head>
<body>
<hello></hello>
<hello></hello>
<hello></hello>
<hello></hello>
</body>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="IsolateScope.js"></script>
</html>
頁面上有四個hello指令
var myModule = angular.module("MyModule", []);
myModule.directive("hello", function() {
return {
restrict: 'AE',
template: '<div><input type="text" ng-model="userName"/>{{userName}}</div>',
replace: true
}
});
給這個指令上面加了input
用來接收用戶的輸入,然后后面加了雙向數(shù)據(jù)綁用來展示輸入的內(nèi)容脑慧,
頁面上有四個input魄眉,因為這里沒有給他創(chuàng)建獨立scope會造成當我們其中一個任意input輸入發(fā)生變化時,會影響其他三個指令實例闷袒。
這是有問題的坑律,他們應該互相不受影響,就沒有辦法獨立去使用了囊骤,
創(chuàng)建獨立scope很簡單只要加一個配置項晃择,scope:{}
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
</head>
<body>
<hello></hello>
<hello></hello>
<hello></hello>
<hello></hello>
</body>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="IsolateScope.js"></script>
</html>
var myModule = angular.module("MyModule", []);
myModule.directive("hello", function() {
return {
restrict: 'AE',
scope:{},
template: '<div><input type="text" ng-model="userName"/>{{userName}}</div>',
replace: true
}
});
這個時候每個指令都有他獨立的scope空間,這樣他們就不會互相影響了也物。
scope的綁定策略
什么是綁定策略
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
</head>
<body>
<div ng-controller="MyCtrl">
<drink flavor="{{ctrlFlavor}}"></drink>
</div>
</body>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="ScopeAt.js"></script>
</html>
首先指令drink 有一個叫flavor一個自定義的屬性宫屠,使用{{}}綁定了一個ctrlFlavor屬性
var myModule = angular.module("MyModule", []);
myModule.controller('MyCtrl', ['$scope', function($scope){
$scope.ctrlFlavor="百威";
}])
myModule.directive("drink", function() {
return {
restrict:'AE',
template:"<div>{{flavor}}</div>",
link:function(scope,element,attrs){
scope.flavor=attrs.flavor;
}
}
});
定義控制器上面賦值一個屬性ctrlFlavor值是百威
定義指令drink
template模板用來顯示{{flavor}}內(nèi)容
link函數(shù)里面把指令屬性flavor的值賦給scope里flavor屬性
實際上template模板用來顯示{{flavor}}內(nèi)容是來自于scope上面的flavor屬性
<div ng-controller="MyCtrl">
<drink flavor="{{ctrlFlavor}}"></drink>
</div>
由于在指令用的這個地方把flavor綁定到了控制器里面的ctrlFlavor上面所以指令里面顯示的應該是百威。
這樣的寫法如果每次都這樣寫會比較累滑蚯,實際上可以通過scope:{flavor:'@'}
這樣的方式去寫浪蹂,link函數(shù)部分就可以不需要了抵栈。
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
</head>
<body>
<div ng-controller="MyCtrl">
<drink flavor="{{ctrlFlavor}}"></drink>
</div>
</body>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="ScopeAt.js"></script>
</html>
var myModule = angular.module("MyModule", []);
myModule.controller('MyCtrl', ['$scope', function($scope){
$scope.ctrlFlavor="百威";
}])
myModule.directive("drink", function() {
return {
restrict:'AE',
scope: {
flavor: '@'
},
template:"<div>{{flavor}}</div>",
/*link:function(scope,element,attrs){
scope.flavor=attrs.flavor;
}*/
}
});
這樣寫和之前也是等價的。
這個是@
綁定坤次,有一個地方需要注意他傳遞的是字符串傳遞的不是對象
scope = 號的綁定
這種綁定是雙向進行綁定
業(yè)務是這樣的dang不僅僅要把$scope上的ctrlFlavor傳遞給指令古劲,當指令來修改了$scope上的ctrlFlavor的內(nèi)容希望也讓控制器里面的內(nèi)容也發(fā)生變化,
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
</head>
<body>
<div ng-controller="MyCtrl">
Ctrl:
<br>
<input type="text" ng-model="ctrlFlavor">
<br>
Directive:
<br>
<drink flavor="ctrlFlavor"></drink>
</div>
</body>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="ScopeEqual.js"></script>
</html>
var myModule = angular.module("MyModule", []);
myModule.controller('MyCtrl', ['$scope', function($scope){
$scope.ctrlFlavor="百威";
}])
myModule.directive("drink", function() {
return {
restrict:'AE',
scope:{
flavor:'='
},
template:'<input type="text" ng-model="flavor"/>'
}
});
通過 scope:{flavor:'='},就把flavor的內(nèi)容綁定到$scope.ctrlFlavor="百威";上面缰猴。
scope & 號的綁定
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
</head>
<body>
<div ng-controller="MyCtrl">
<greeting greet="sayHello(name)"></greeting>
<greeting greet="sayHello(name)"></greeting>
<greeting greet="sayHello(name)"></greeting>
</div>
</body>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="ScopeAnd.js"></script>
</html>
有greeting 指令绢慢,這個指令里面要調(diào)用控制器上面的方法叫sayHello
var myModule = angular.module("MyModule", []);
myModule.controller('MyCtrl', ['$scope', function($scope){
$scope.sayHello=function(name){
alert("Hello "+name);
}
}])
myModule.directive("greeting", function() {
return {
restrict:'AE',
scope:{
greet:'&'
},
template:'<input type="text" ng-model="userName" /><br/>'+
'<button class="btn btn-default" ng-click="greet({name:userName})">Greeting</button><br/>'
}
});
js中有一個控制器,作用域上有sayHello方法洛波,彈參數(shù)出來胰舆。
寫了greeting指令,寫了scope:{greet:'&'},
在模板里面用一個按鈕調(diào)用greet函數(shù)
這個函數(shù)在頁面上綁定控制器上面的sayHello方法
AngularJS內(nèi)置的指令
http://ngnice.com/ AngularJS-api
<html ng-app='TestFormModule'>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="FormBasic.js"></script>
</head>
<body>
<form name="myForm" ng-submit="save()" ng-controller="TestFormModule">
<input name="userName" type="text" ng-model="user.userName" required/>
<input name="password" type="password" ng-model="user.password" required/>
<input type="submit" ng-disabled="myForm.$invalid"/>
</form>
</body>
</html>
var appModule = angular.module('TestFormModule', []);
appModule.controller("TestFormModule",function($scope){
$scope.user={
userName:'damoqiongqiu',
password:''
};
$scope.save=function(){
alert("保存數(shù)據(jù)!");
}
});
<!doctype html>
<html ng-app>
<head>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="FormAdv1.js"></script>
</head>
<body>
<div ng-controller="Controller">
<form name="form" class="css-form" novalidate>
Name:
<input type="text" ng-model="user.name" name="uName" required /><br/>
E-mail:
<input type="email" ng-model="user.email" name="uEmail" required /><br/>
<div ng-show="form.uEmail.$dirty && form.uEmail.$invalid">
Invalid:
<span ng-show="form.uEmail.$error.required">Tell us your email.</span>
<span ng-show="form.uEmail.$error.email">This is not a valid email.</span>
</div>
Gender:<br/>
<input type="radio" ng-model="user.gender" value="male" />
male
<input type="radio" ng-model="user.gender" value="female" />
female<br/>
<input type="checkbox" ng-model="user.agree" name="userAgree" required />
I agree:
<input ng-show="user.agree" type="text" ng-model="user.agreeSign" required />
<div ng-show="!user.agree || !user.agreeSign">
Please agree and sign.
</div>
<br/>
<button ng-click="reset()" ng-disabled="isUnchanged(user)">
RESET
</button>
<button ng-click="update(user)" ng-disabled="form.$invalid || isUnchanged(user)">
SAVE
</button>
</form>
</div>
</body>
</html>
function Controller($scope) {
$scope.master = {};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.isUnchanged = function(user) {
return angular.equals(user, $scope.master);
};
$scope.reset();
}
實例解析Expander
<html ng-app='expanderModule'>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="ExpanderSimple.css"/>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="ExpanderSimple.js"></script>
</head>
<body>
<div ng-controller='SomeController'>
<expander class='expander' expander-title='title'>
{{text}}
</expander>
</div>
</body>
</html>
定義一個控制器 蹬挤,寫入expander指令缚窿,后面的expander-title='title'是使用ag綁定策略來進行綁定,
var expanderModule=angular.module('expanderModule', []);
expanderModule.directive('expander', function() {
return {
restrict : 'EA',
replace : true,
transclude : true,
scope : {
title : '=expanderTitle'
},
template : '<div>'
+ '<div class="title" ng-click="toggle()">{{title}}</div>'
+ '<div class="body" ng-show="showMe" ng-transclude></div>'
+ '</div>',
link : function(scope, element, attrs) {
scope.showMe = false;
scope.toggle = function() {
scope.showMe = !scope.showMe;
}
}
}
});
expanderModule.controller('SomeController',function($scope) {
$scope.title = '點擊展開';
$scope.text = '這里是內(nèi)部的內(nèi)容焰扳。';
});
首先directive定義一個指令expander
restrict : 'EA', 可以用元素也可以用屬性倦零,
replace : true, 會替換
transclude : true, 內(nèi)部內(nèi)容是可以變換的
scope : {
title : '=expanderTitle'
},
//= 等于號這樣一個等值綁定 綁定expanderTitle這樣一個東西,
這個東西就是頁面上寫的
<expander class='expander' expander-title='title'>
{{text}}
</expander>
template
template : '<div>'
+ '<div class="title" ng-click="toggle()">{{title}}</div>'
+ '<div class="body" ng-show="showMe" ng-transclude></div>'
+ '</div>',
template里面有一個ng-click綁定到toggle()
這樣一個方法上面吨悍,這個方法是有指令link
這個函數(shù)里面提供出來的扫茅,很顯然是指令內(nèi)部去使用,外部是調(diào)取不到這個方法的育瓜,
link : function(scope, element, attrs) {
scope.showMe = false;
scope.toggle = function() {
scope.showMe = !scope.showMe;
}
}
看看ng-show
ng-show
是用來進行顯示和隱藏的切換的葫隙,他會根據(jù)showMe
的屬性是不是為true
來決定這個div
到底顯不顯示。
以上是一個簡單指令的例子
Accordion
css
.expander {
border: 1px solid black;
width: 250px;
}
.expander>.title {
background-color: black;
color: white;
padding: .1em .3em;
cursor: pointer;
}
.expander>.body {
padding: .1em .3em;
}
html
<html ng-app="expanderModule">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="Accordion.css"/>
<script src="framework/angular-1.3.0.14/angular.js"></script>
<script src="Accordion.js"></script>
</head>
<body ng-controller='SomeController' >
<accordion>
<expander class='expander' ng-repeat='expander in expanders' expander-title='expander.title'>
{{expander.text}}
</expander>
</accordion>
</body>
</html>
這里面指令進了嵌套躏仇,外面是個accordion
恋脚,內(nèi)部是expander
這樣一個指令,expander
使用ng-repeat='expander in expanders'
來進行迭代焰手,他會根據(jù)expanders
數(shù)組里面內(nèi)容來決定創(chuàng)建多少個expander
糟描,
javascript
var expModule=angular.module('expanderModule',[])
expModule.directive('accordion', function() {
return {
restrict : 'EA',
replace : true,
transclude : true,
template : '<div ng-transclude></div>',
controller : function() {
var expanders = [];
this.gotOpened = function(selectedExpander) {
angular.forEach(expanders, function(expander) {
if (selectedExpander != expander) {
expander.showMe = false;
}
});
}
this.addExpander = function(expander) {
expanders.push(expander);
}
}
}
});
expModule.directive('expander', function() {
return {
restrict : 'EA',
replace : true,
transclude : true,
require : '^?accordion',
scope : {
title : '=expanderTitle'
},
template : '<div>'
+ '<div class="title" ng-click="toggle()">{{title}}</div>'
+ '<div class="body" ng-show="showMe" ng-transclude></div>'
+ '</div>',
link : function(scope, element, attrs, accordionController) {
scope.showMe = false;
accordionController.addExpander(scope);
scope.toggle = function toggle() {
scope.showMe = !scope.showMe;
accordionController.gotOpened(scope);
}
}
}
});
expModule.controller("SomeController",function($scope) {
$scope.expanders = [{
title : 'Click me to expand',
text : 'Hi there folks, I am the content that was hidden but is now shown.'
}, {
title : 'Click this',
text : 'I am even better text than you have seen previously'
}, {
title : 'Test',
text : 'test'
}];
});
expander
指令中require : '^?accordion',
依賴外部的accordion
,
在link
里面就能接收到第四個參數(shù)accordionController
通過參數(shù)accordionController
就可以跟外層的指令來進行一些交互书妻,
accordion
里面通過controller
暴露了一些方法出來船响,
controller : function() {
var expanders = [];
this.gotOpened = function(selectedExpander) {
angular.forEach(expanders, function(expander) {
if (selectedExpander != expander) {
expander.showMe = false;
}
});
}
this.addExpander = function(expander) {
expanders.push(expander);
}
}
這樣expander
就能通過accordionController
來調(diào)用
效果
第三方指令庫,借助指令庫加強開發(fā)速度