写这篇文章的初衷有如下几点:html
1.最近项目中须要用到ng的自定义指令,而且还涉及到自定义指令的嵌套。
2.百度和谷歌找到的答案都不尽人意。前端因此想着本身写一篇得了。web
事先说明,鄙人刚入前端4月有余,属于新蛋一枚,也是初次写博客(第一次就这么献给sf了。),我尽本身最大的努力把我想表达的意思表达出来。好了,废话很少说,直接奔入主体。chrome
首先,还不知道ng自定义指令的童鞋请戳这篇文章。
http://www.cnblogs.com/lvdaba...
这篇文章分了上中下,三篇,讲ng自定义指令已经很详细了。app
其次,还不知道ng自定义指令中的transclusion是啥玩意童鞋请戳这篇文章。
http://www.html-js.com/articl...
这篇文章采用口语化的表达方式诙谐的讲述了何为transclusion。ui
好了,到这里,咱们正式再次进入主题。spa
咱们先建立一个app,代码以下rest
var app=angular.module('myApp', []); app.controller("testController",function($scope){ });
咱们都知道transclusion是自定义指令的的配置项,它的值有如下几种状况:code
1.boolean类型,也就是为true,或者false,固然,默认为false。
2.Object类型,能够是一个对象。
3.element类型,还能够是一个元素。(表示:我目前尚未玩过element。)htm
好了,先来讲说其值为boolean类型的时候吧。
建立一个自定义指令,设置其transclusion为true。代码以下:
app.directive('popSelect',[function(){ return { restrict: 'AE', scope:{ }, transclude:true, replace:true, template: '<div>'+ '<div>'+ '<input type="text" ng-model="input" ng-focus="hasDate=true"/>'+ '</div>'+ '<div ng-transclude></div>'+ '<div>这是popselect指令的内容</div>'+ '</div>', link:function(scope, elem, attrs){ } } }]);
你们应该有看到在template里面多了一个东西是'<div ng-transclude></div>',看到就能够了,在这里留个悬念。
既然是自定义指令的嵌套,那好歹也要有两个指令吧,废话很少说,再建立一个指令,此指令做为儿子被别人嵌套,而上面那个嵌套别人的指令咱们叫作父亲。代码以下:
app.directive('childElem',[function(){ return { restrict: 'AE', replace:true, template:'<div>'+ '<div>这是child指令的内容</div>'+ '</div>', link:function(scope, elem, attrs){ } } }])
父亲和儿子都建立完成了,那咱们来看看html里面是怎么嵌套了。直接上代码:
<pop-select> <child-elem></child-elem> </pop-select>
没错,html就是这么简单就能够了,看看页面是啥效果:
看到没,儿子的template内容被嵌入进父亲的template(姑且认为是template吧),那么它被嵌入到父亲的template的哪里了呢,咱们看看控制台。
你们有没有发现什么,上图红框中的位置是否是刚好就是父亲的template的'<div ng-transclude></div>'这句话所在位置呀。
没错,只要你的指令中嵌套其余的指令,那么你在父亲的配置项中设置transclude:true,而且在template中你须要的地方加上'<div ng-transclude></div>'这句嵌套话,那么ng将自动把儿子的内容加入到'<div ng-transclude></div>'这个标签中来,请仔细看控制台红框的图片。
如今你们自动transclude:true怎么用了吧。
这里有人就要问了:你这是嵌套一个儿子啊,若是我家钱多,我土豪,我要生不少个儿子那怎么办?
那此时就要使用transclude的值为object了。废话很少说再次上代码。
app.directive('parentDirective',[function(){ return { restrict: 'AE', transclude:{ 'child1':"childElem", 'child2':"childElem2", 'child3':"childElem3" }, replace:true, template: '<div>'+ '<div>'+ '<input type="text" ng-model="input" value="这是parant指令"/>'+ '</div>'+ '<div ng-transclude="child2"></div>'+ '<div ng-transclude="child3"></div>'+ '<div ng-transclude="child1"></div>'+ '</div>', link:function(scope, elem, attrs){ } } }]);
你们注意到这一次父亲的transclude是一个对象
{ 'child1':"childElem", 'child2':"childElem2", 'child3':"childElem3" }
在父亲的template中还有这样三句话:
'<div ng-transclude="child2"></div>'+ '<div ng-transclude="child3"></div>'+ '<div ng-transclude="child1"></div>'+
你们可能注意到这三句话中的child1,child2,child3怎么和父亲的transclude值中的三个属性child1,child2,child3一毛同样啊。猜猜呗,我想有人应该知道是怎么玩了。
那父亲的transclude值中的childElem,childElem2,childElem3这三个是啥玩意?别急嘛。这不,父亲尚未儿子吗?来,给他三个儿子。
首先是大儿子:
app.directive('childElem',[function(){ return { restrict: 'AE', replace:true, template:'<div>'+ '<div>这是child指令的内容</div>'+ '</div>', link:function(scope, elem, attrs){ } } }])
而后是二儿子:
app.directive('childElem2',[function(){ return { restrict: 'AE', replace:true, template:'<div>'+ '<div>这是childElem2指令的内容</div>'+ '</div>', link:function(scope, elem, attrs){ } } }])
最后是三儿子:
app.directive('childElem3',[function(){ return { restrict: 'AE', replace:true, template:'<div>'+ '<div>这是childElem3指令的内容</div>'+ '</div>', link:function(scope, elem, attrs){ } } }])
儿子们到齐了,接下来就该html了。继续上代码:
<parent-directive> <child-elem></child-elem> <child-elem2></child-elem2> <child-elem3></child-elem3> </parent-directive>
那么页面效果是啥样子呢?看下图:
看,三个的儿子的内容和父亲的内容都显示出来了。
让咱们再看看控制台:
三个红框中的内容就是三个儿子的template了。
你们如今应该明白了吧,没错。当父亲的transclude是一个对象时,那么属性名就是你本身起的名字, 值就是你须要嵌入的儿子的名字。而后你再在父亲的template里面写上'<div ng-transclude="你起好的属性名字"></div>',这样ng就能知道你是想把儿子嵌入到父亲的哪里了。
好了,尚未不明白的么。若是不明白请看第二遍。哈哈、
最后,附上本例中的所有代码。
<!DOCTYPE html> <html ng-app="myApp"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> </head> <body ng-controller="testController"> <h1>嵌套一个指令</h1> <pop-select> <child-elem></child-elem> </pop-select> <h1> </h1> <h1>嵌套多个指令</h1> <parent-directive> <child-elem></child-elem> <child-elem2></child-elem2> <child-elem3></child-elem3> </parent-directive> </body> <script src="https://staticfile.qnssl.com/angular.js/1.5.0-rc.0/angular.min.js"></script> <script> var app=angular.module('myApp', []); app.controller("testController",function($scope){ }); app.directive('popSelect',[function(){ return { restrict: 'AE', scope:{ }, transclude:true, replace:true, template:'<div>'+ '<div><input type="text" ng-model="input" ng-focus="hasDate=true"/></div>'+ '<div ng-transclude></div>'+ '<div>这是popselect指令的内容</div>'+ '</div>', link:function(scope, elem, attrs){ } } }]); app.directive('childElem',[function(){ return { restrict: 'AE', replace:true, template:'<div>'+ '<div>这是child指令的内容</div>'+ '</div>', link:function(scope, elem, attrs){ } } }]) app.directive('parentDirective',[function(){ return { restrict: 'AE', transclude:{ 'child1':"childElem", 'child2':"childElem2", 'child3':"childElem3" }, replace:true, template: '<div>'+ '<div>'+ '<input type="text" ng-model="input" value="这是parant指令"/>'+ '</div>'+ '<div ng-transclude="child2"></div>'+ '<div ng-transclude="child3"></div>'+ '<div ng-transclude="child1"></div>'+ '</div>', link:function(scope, elem, attrs){ } } }]); app.directive('childElem2',[function(){ return { restrict: 'AE', replace:true, template:'<div>'+ '<div>这是childElem2指令的内容</div>'+ '</div>', link:function(scope, elem, attrs){ } } }]) app.directive('childElem3',[function(){ return { restrict: 'AE', replace:true, template:'<div>'+ '<div>这是childElem3指令的内容</div>'+ '</div>', link:function(scope, elem, attrs){ } } }]) </script> </html>
谢谢你们的耐心观看。