初衷

写这篇文章的初衷有以下几点:

1.最近项目中需要用到ng的自定义指令,并且还涉及到自定义指令的嵌套。
2.百度和谷歌找到的答案都不尽人意。

所以想着自己写一篇得了。

事先声明

事先说明,鄙人刚入前端4月有余,属于新蛋一枚,也是初次写博客(第一次就这么献给sf了。),我尽自己最大的努力把我想表达的意思表达出来。好了,废话不多说,直接奔入主体。

前提

首先,还不知道ng自定义指令的童鞋请戳这篇文章。
http://www.cnblogs.com/lvdaba...
这篇文章分了上中下,三篇,讲ng自定义指令已经很详细了。

其次,还不知道ng自定义指令中的transclusion是啥玩意童鞋请戳这篇文章。
http://www.html-js.com/articl...
这篇文章采用口语化的表达方式诙谐的讲述了何为transclusion。

好了,到这里,我们正式再次进入主题。

transclusion的值

我们先创建一个app,代码如下

var app=angular.module('myApp', []);
app.controller("testController",function($scope){
    
});

我们都知道transclusion是自定义指令的的配置项,它的值有以下几种情况:

1.boolean类型,也就是为true,或者false,当然,默认为false。
2.Object类型,可以是一个对象。
3.element类型,还可以是一个元素。(表示:我目前还没有玩过element。)

transclusion为boolean时

好了,先来说说其值为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怎么用了吧。

transclusion为object时

这里有人就要问了:你这是嵌套一个儿子啊,如果我家钱多,我土豪,我要生很多个儿子那怎么办?

那此时就要使用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>&nbsp;</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>

谢谢大家的耐心观看。


skycity
147 声望6 粉丝

路漫漫其修远兮