例子1:从最简单的开始
<!DOCTYPE html> <html lang="en" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>自动以指令1</title> <script src="../js/angular.min.js"></script> </head> <body> <hello></hello> </body> <script> var appModule=angular.module('myApp',[]); appModule.directive('hello',function(){ return { restrict:'E', template:'<div>Hello World!</div>', replace:true } }); </script> </html>对于以上代码里面的<hello>标签,浏览器显然是不认识的,它唯一能做的事情就是无视这个标签。那么,为了让浏览器能够认识这个标签,我们需要使用Angular来定义一个hello指令( 本质上说就是自己来把<hello>这种玩意儿替换成浏览器能识别的那些标准HTML标签)。
这里定义指令使用了三个设置选项:
restrict:指令声明方式选项。告之这个指令为元素(E)、属性(A)、类(C)、注释(M)
template:模板
replace:替换选项。为true,则用template计算后内容替换指令名称所在内容。
例子2:子标签transclude(变换)
<!DOCTYPE html> <html lang="en" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>自定义指令2</title> <script src="../js/angular.min.js"></script> </head> <body> <h2>包含内容的hello</h2> <hello> <br/> <span>原始的内容,</span><br/> <span>还会在这里。</span> </hello> <h2>不包含内容的hello</h2> <hello> </hello> <script> var appModule=angular.module("myApp",[]); appModule.directive("hello",function() { return { restrict:'E', template:'<div> Hi there<span ng-transclude></span></div>', transclude:true }; }); </script> </body> </html>和第一个例子对比,这个例子的JS和HTML代码都略有不同,JS代码里面多了一个transclude: true,HTML代码里面在<hello>内部出现了子标签。
按照我们在第一个例子中的说法,指令的作用是把我们自定义的语义化标签替换成浏览器能够认识的HTML标签。那好,如果我们自定义的标签内部出现了子标签,应该如何去处理呢?很显然,transclude就是用来处理这种情况的。
对于当前这个例子,transclude的作用可以简化地理解成:把<hello>标签替换成我们所编写的HTML模板,但是<hello>标签内部的内容保持不变。
很显然,由于我们没有加replace:true选项,所以<hello>标签还在,没有被替换掉。同时,通过这个例子你还还会发现一 个暗藏的属性,那就是浏览器实际上非常智能,虽然它并不认识<hello>这个标签,但是页面没有出错,它只是默默地把这个标签忽略掉了!怎 么样?是不是碉堡了?
你可以自己在上面的JS代码里面加上replace:true,然后再看生成的HTML结构。
例子3:一个复杂一点的例子Expander
<!DOCTYPE html> <html lang="en" ng-app="expanderModule"> <head> <meta charset="UTF-8"> <title>实例3:一个复杂一点的例子Expander</title> <script src="../js/angular.min.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='SomeController'> <expander class='expander' expander-title='title'> {{text}} </expander> </div> <script> 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 = '这里是内部的内容。'; }); </script> </body> </html>
实例4:一个综合的例子
<!DOCTYPE html> <html lang="en" ng-app="expanderModule"> <head> <meta charset="UTF-8"> <title>实例5:一个综合的例子</title> <script src='../js/angular.min.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 ng-controller='SomeController' > <accordion> <expander class='expander' ng-repeat='expander in expanders' expander-title='expander.title'> {{expander.text}} </expander> </accordion> <script> 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' }]; }); </script> </body> </html>