angularjs指令中的replace与transclude参数

replace, 是否替换掉自定义的指令, 默认是false

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',
                template:"<span>hello</span>"
              }
            });   
        </script>
        <style type="text/css">
        </style>
    </head>
    <body ng-app="myapp">
       <cust></cust>
    </body>

</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

<!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,
                template:"<div>world</div>"
              }
            });   
        </script>
        <style type="text/css">
        </style>
    </head>
    <body ng-app="myapp">
       <cust>hello</cust>
    </body>

</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是关键.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值