指令初体验
四种匹配模式:
E 元素 <menu></menu>
A(default) 属性 <div menu=></div>
C 样式 <div class="menu"></div>
M 注释 <!-- directive:menu xxx -->
指令运行三阶段:
加载阶段:找到ng-app指令,确定应用边界
编译阶段:遍历DOM,根据指令template、replace、transclue转换DOM,运行compile函数
链接阶段:运行Link,操作DOM、绑定事件监听器
模板的重用:
使用缓存:
var myModule = angular.module("MyModule",[]);
myModule.run(function($templateCache){
$templateCache.put("hello.html","<div>Hello</div>");
});
绑定指令
myModule.directive("hello",function($templateCache){
return {
restrict:'AECM',
template:$templateCache.get("hello.html"),
replace:true
}
});
嵌套指令:
<hello>
<div>如果使用replace:true,这里就会被替换</div>
</hello>
使用transclude:true,template:"<div>Hello everyone!<div ng-transclude></div></div>"被覆盖的内容会放进来就可以显示了
简单的指令复用:
js:
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();
}
}
});
注意,controller里面写暴露给外面使用的方法
link里面写简单简单指令操作
html:
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<title>ag_test</title>
</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>力量速度加成</superman>
</div>
</div>
<div class="row">
<div class="col-md-3">
<superman strength speed light>力量速度光线加成</superman>
</div>
</div>
</body>
<script src="js/angular.min.js"></script>
<script src="js/dgcr.js"></script>
</html>
独立scope:
如果不使用独立scope会出现所有的ng-model公用,但是使用了scope:{}就可以解决这个问题
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绑定策略:@:字符串,=双向绑定,&父层函数
@测试:
html:
<div ng-controller="MyCtrl">
<drink flavor="{{ctrlFlavor}}"></drink>
</div>
绑定指令下的flavor:
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;
}
}
});
现在有更简单的写法:
return {
restrict:'AE',
scope:{
flavor:'@'
},
template:'<div>{{flavor}}</div>'
}
=的双向绑定:
<div ng-controller="MyCtrl">
Ctrl:
<br>
<input type="text" ng-model="ctrlFlavor">
<br>
Directive:
<br>
<drink flavor="ctrlFlavor"></drink>
</div>
js实现绑定:
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" />'
}
});
可以实现同步变化
&:
html:
<div ng-controller="MyCtrl">
<greeting greet="sayHello(name)"></greeting>
<greeting greet="sayHello(name)"></greeting>
<greeting greet="sayHello(name)"></greeting>
</div>
js:
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/>'
}
});
sayHello大小写HTML和JS务必一致。
内置指令:
form指令:
可以嵌套
自动校验、防止重复提交
扩展input的type text,number,url,email,radio,checkbox,hidden,button,submi,reset
内置css ng-valid、ng-invalid、ng-pristine、ng-dirty
内置检验器:require,minlength,maxlength
简单Form的使用:
html:
<form name="myForm" ng-submit="save()" ng-controller="TestFormModule">
<input type="text" name="userName" ng-model="user.userName" required />
<input type="password" name="password" ng-model="user.password" required />
<input type="submit" ng-disabled="myForm.$invalid" />
</form>
js:
var appModule = angular.module("TestFormModule",[]);
appModule.controller("TestFormModule",function($scope){
$scope.user = {
username:'xjh',
password:''
};
$scope.save = function(){
alert('保存成功');
}
});
自定义指令:
简单与现实菜单的实现:
js:
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){
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'
}];
})
html:
<body ng-controller="SomeController">
<accordion>
<expander class='expander' ng-repeat='expander in expanders' expander-title='expander.title'>
{{expander.text}}
</expander>
</accordion>
</body>
由于内部机制原因,前台的expander-title在js中需使用expanderTitle方可识别使用。
UI插件:
miniui.com
sencha
http://docs.kissyui.com/
ng-grid
以上内容参考大漠穷秋教学视频