replace, 是否替换掉自定义的指令, 默认是false
Element形式
<!DOCTYPE html>
<html></html>
可以看到cust指令还保留在html里,模板中的内容包含在其中.
attribute形式
<body ng-app="myapp">
<div cust></div>
</body>
可以看到div还保留在html中.
replace:true
Element形式
可以看到,<cust></cust>不见了.
Attribute形式
div不见了替换为span,但是span中有cust属性.
transclude是保留自定义指令子元素中的内容
默认是false
</html>
可以看到原先cust中的hello 没了,没有被保留下来,所以如果想要保留,那么就要transclude:true,并且在templace中相应的地方使用ng-transclude说明嵌入在哪.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="bootstrap.min.css">
<script src="jquery.min.js"></script>
<script src="angular.min.js"></script>
<script src="bootstrap.min.js"></script>
<script type="text/javascript">
var app = angular.module('myapp', []);
app.directive('cust', function(){
return {
restrict: 'EA',
replace: true,
transclude: true,
template:"<div>world<div ng-transclude></div></div>"
}
});
</script>
<style type="text/css">
</style>
</head>
<body ng-app="myapp">
<cust>hello</cust>
</body>
</html>
可以看到hello被嵌入进了div中,angular还自动将其包裹在span中.
当然如果你本来就有了span, angular是不会再加span的.
上面的保留了hello,hello是cust的子元素,如果我想把cust也保留嵌入模板该怎么做,你或许说把replace改为false不就保留了.这样是可以保留,但跟我要说的不一样.
如果我把body改成<label cust>hello</label>,我想保留label该怎么做,现在只能把hello嵌入模板.
所以接下来要说的就是transclude:'element',把子元素和本身都保留下来.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="bootstrap.min.css">
<script src="jquery.min.js"></script>
<script src="angular.min.js"></script>
<script src="bootstrap.min.js"></script>
<script type="text/javascript">
var app = angular.module('myapp', []);
app.directive('cust', function(){
return {
restrict: 'EA',
replace: true,
transclude: 'element',
template:"<div>world<div ng-transclude></div></div>"
}
});
</script>
<style type="text/css">
</style>
</head>
<body ng-app="myapp">
<label cust>hello</label>
</body>
</html>
可以看到label保留下来了.
下面最后一个比较6,
将上面的代码中replace改为false
一切灰飞烟灭只留下了注释.
这是为什么呢,跟踪源码
if (directiveValue == 'element') {
hasElementTranscludeDirective = true;
terminalPriority = directive.priority;
$template = $compileNode;
$compileNode = templateAttrs.$$element =
jqLite(document.createComment(' ' + directiveName + ': ' +
templateAttrs[directiveName] + ' '));
compileNode = $compileNode[0];
replaceWith(jqCollection, sliceArgs($template), compileNode);
childTranscludeFn = compile($template, transcludeFn, terminalPriority,
replaceDirective && replaceDirective.name, {
// Don't pass in:
// - controllerDirectives - otherwise we'll create duplicates controllers
// - newIsolateScopeDirective or templateDirective - combining templates with
// element transclusion doesn't make sense.
//
// We need only nonTlbTranscludeDirective so that we prevent putting transclusion
// on the same element more than once.
nonTlbTranscludeDirective: nonTlbTranscludeDirective
});
} else {
$template = jqLite(jqLiteClone(compileNode)).contents();
$compileNode.empty(); // clear contents
childTranscludeFn = compile($template, transcludeFn);
}
}
if (directive.template) {
hasTemplate = true;
assertNoDuplicate('template', templateDirective, directive, $compileNode);
templateDirective = directive;
directiveValue = (isFunction(directive.template))
? directive.template($compileNode, templateAttrs)
: directive.template;
directiveValue = denormalizeTemplate(directiveValue);
if (directive.replace) {
replaceDirective = directive;
if (jqLiteIsTextNode(directiveValue)) {
$template = [];
} else {
$template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue)));
}
compileNode = $template[0];
if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {
throw $compileMinErr('tplrt',
"Template for directive '{0}' must have exactly one root element. {1}",
directiveName, '');
}
replaceWith(jqCollection, $compileNode, compileNode);
var newTemplateAttrs = {$attr: {}};
// combine directives from the original node and from the template:
// - take the array of directives for this element
// - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)
// - collect directives from the template and sort them by priority
// - combine directives as: processed + template + unprocessed
var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));
if (newIsolateScopeDirective) {
markDirectivesAsIsolate(templateDirectives);
}
directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
ii = directives.length;
} else {
$compileNode.html(directiveValue);
}
}
可以看到,两次replaceWith是关键.