目录
article
AngularJS 之 Directive 指令详解
AngularJS 之 Directive 指令详解
实现语义化标签
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>实现语义化标签</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.js">
</script>
</head>
<body>
<div ng-controller="MyController">
<hello></hello>
</div>
<script>
var appModule = angular.module('app',);
appModule.directive('hello',function(){
return{
restrict:'E',
template:'<div>Hi there</div>',
replace:true
};
});
appModule.controller('MyController',
function ($scope,$timeout){
}
);
</script>
</body>
</html>
指令声明方式选项 (restrict):
- E:元素。例:
<my-menu title=Products></my-menu> - A:属性。例:
<div my-menu=Products></div> - C:元素。例:
<div class=my-menu:Products></div> - M:元素。例:
<!-- directive:my-menu Products -->
如果我们需要替换的 HTML 标签很长,显然不能用 拼接字符串的方式来写,这时候我们可以用templateUrl来替代template,从而可以把模板写到一个独立的 HTML 文件中。
transclude(变换)
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>变换</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.js">
</script>
</head>
<body>
<div ng-controller="MyController">
<hello>
<br/>
<span>原始的内容</span>
<br/>
<span>还会在这里</span>
<br/>
<p>新内容</p>
</hello>
<hello>
</hello>
</div>
<script>
var appModule = angular.module('app',);
appModule.directive('hello',function(){
return{
restrict:'E',
template:'<div>Hi there<span ng-transclude></span></div>',
transclude:true
};
});
appModule.controller('MyController',
function ($scope,$timeout){
}
);
</script>
</body>
</html>
和第一个例子对比,这个例子的 JS 和 HTML 代码都略有不同,JS 代码里面多了一个transclude: true,HTML 代码里面在<hello>内部出现了子标签。
transclude的作用可以简化地理解成:把<hello>标签替换成我们所编写的 HTML 模板,但是<hello>标签内部的内容保持不变。
compile和link
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>编译和连接</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.js">
</script>
</head>
<body>
<div ng-controller="MyController">
<div ng-repeat='thing in things'>
{{thing}}.<hello></hello>
</div>
</div>
<script>
var appModule = angular.module('app',);
appModule.directive('hello',function(){
return{
restrict:'E',
template:'<div>Hi there</div>',
replace:true
};
});
appModule.controller('MyController',
function ($scope){
$scope.things = [1,2,3,4,5,6];
}
);
</script>
</body>
</html>
directive指令的本质其实是一个替换过程。 这个过程分为两个阶段,分别为compile和link。
更好的一个例子
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>编译和连接2</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.js">
</script>
<style>
.expander{
border:1px solid black;
width:250px;
}
.expander>.title{
background-color:black;
color:white;
padding: .1em .3em;
cursor:pointer;
}
.expander>.body{
padding: .1em .3em;
}
</style>
</head>
<body>
<div ng-controller="MyController">
<expander class='expander' expander-title='title'>
{{text}}
</expander>
</div>
<script>
var appModule = angular.module('app',);
appModule.directive('expander',function(){
return{
restrict:'EA',
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 toggle(){
scope.showMe = !scope.showMe;
}
},
replace:true,
transclude:true
};
});
appModule.controller('MyController',
function ($scope){
$scope.title = '点击展开';
$scope.text = '这里是内部的内容。';
}
);
</script>
</body>
</html>
综合实例
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>directive指令综合</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.js">
</script>
</head>
<body ng-controller="MyController">
<div>
<accordion>
<expander class="expander" ng-repeat='expander in expanders' expander-title='expander.title'>
{{expander.text}}
</expander>
</accordion>
</div>
<script>
var appModule = angular.module('app',);
appModule.directive('accordion',function(){
return{
restrict:'EA',
template:'<div ng-transclude></div>',
replace:true,
transclude:true,
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);
}
}
}
});
appModule.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);
}
}
}
});
appModule.controller('MyController',
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'
}
];
}
);
</script>
</body>
</html>