transclude可以设置为false(默认),true或者对象三种值,如果不设该属性就默认为false,也就是说你不需要将该指令所在元素包含的内容嵌入到模板中。
一、transclude设置为true
当transclude为true的时候,这时指令所在元素包含的内容会被嵌入到模板中有ng-transclude指令的元素中,例如:
<hello>
<p>hello</p>
<hello>
angular.module("app", []).directive('hello', ['', function() {
return {
restrict: 'E',
template: '<div ng-transclude></div>',
transclude: true,
scope:{}
}
}]);
运行结果
<hello>
<div ng-transclude>
<p>hello</p>
</div>
<hello>
二、transclude设置为对象
当指令元素包含的内容需要嵌入到指令模板不同地方的时候,这个时候就要把transclude设置为对象
<panel>
<panel-header>标题</panel-header>
<panel-body>内容</panel-body>
<panel-footer>页脚</panel-footer>
</panel>
angular.module("app", []).directive('panel', ['', function() {
return {
restrict: 'E',
replace: true,
transclude: {
'header': '?panelHeader',
'body' : 'panelBody',
'footer': '?panelFooter'
},
template: '
<div class="panel">
<div class="panel-header" ng-transclude="header"></div>
<div class="panel-body" ng-transclude="body"></div>
<div class="panel-footer" ng-transclude="footer"></div>
</div>'
}
}]);
运行结果
<div class="panel">
<div class="panel-header" ng-transclude="header">
<panel-header class="ng-binding ng-scope">标题</panel-header>
</div>
<div class="panel-body" ng-transclude="body">
<panel-body class="ng-binding ng-scope">内容</panel-body>
</div>
<div class="panel-footer" ng-transclude="footer">
<panel-footer class="ng-binding ng-scope">页脚</panel-footer>
</div>
</div>
这里指令元素内部有三个指令,这三个指令(panel-header、panel-body、panel-footer)必须以E的形式调用,它们分别要插入到模板的不同位置,tranclude指定了要插入的位置,transclude是一个键值对的对象,key指定了要插入模板的位置,value就是要插入的内容,?代表这个嵌入点不一定有指令存在,否则必须在这个点插入指令,不然会报错。
值得注意的是,这个实例也证明了一点,指令包含的元素的作用域继承自指令的父作用域而不是隔离作用域。
三、$transclude
除了使用ng-transclude指令指定内容嵌入的地方外,还可以使用$transclude指令实现。
<hello>
<span></span>
</hello>
angular.module("app", []).directive('hello', () =>{
return {
restrict: 'E',
transclude: true,
controller: ['$scope', '$element', '$transclude', function ($scope, $element, $transclude) {
$transclude(function(clone) {
//$element.find只能通过标签名进行查找
$element.find('span').append(clone);
});
}],
template: '<div><span></span></div>',
scope: {}
}
});
运行结果
<hello>
<div>
<span>
<span class="ng-binding ng-scope"></span>
</span>
</div>
</hello>
其中控制器中的$element就是编译了之后的模板,而$transclude中的参数clone则是被编译了的指令包含的内容。两者可以同时对模板和内容进行处理。
四、compile
除了使用ng-transclude指令指定内容嵌入的地方外,还可以使用compile中指定第三个transcludeFn参数
<hello>
<span></span>
</hello>
angular.module("app", []).directive('hello', ['', function() {
return {
restrict: 'E',
transclude: true,
compile: function(tElement, tAttrs, transcludeFn) {
return function(scope, element, attrs) {
scope.action = "hello";
transcludeFn(scope, function(clone) {
element.find('span').append(clone);
});
};
},
template: '<div><span></span></div>',
scope: {}
}
}]);
<hello>
<div>
<span>
<span class="ng-binding ng-scope"></span>
</span>
</div>
</hello>
这个文件实现了以上控制器中相同的功能,transcludeFn接受两个参数,一个scope作用域,一个函数,和controller一样,这个函数的参数clone就是编译之后的要嵌入的内容。唯一不同的是,编译这个clone的作用域是传进去的第一个参数,而controller中clone是继承了指令的父作用域。