您的位置:首页 > Web前端 > AngularJS

详解angularjs指令中的replace与transclude参数

2016-08-04 15:35 337 查看
1.replace, 是否替换掉自定义的指令, 默认是false

a.Element形式:
        <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>

结果:

可以看到cust指令还保留在html里,模板中的内容包含在其中.



b.attribute形式:

<body ng-app="myapp">

       <div cust></div>

    </body>

结果:

可以看到div还保留在html中.



2.replace:true

a.Element形式:



可以看到,<cust></cust>不见了.

b.Attribute形式



div不见了替换为span,但是span中有cust属性.

3.transclude是保留自定义指令子元素中的内容

a.默认是false
        <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>



可以看到原先cust中的hello 没了,没有被保留下来,所以如果想要保留,那么就要transclude:true,并且在templace中相应的地方使用ng-transclude说明嵌入在哪.

b.默认是true

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



可以看到hello被嵌入进了div中,angular还自动将其包裹在span中.

当然如果你本来就有了span, angular是不会再加span的.

c.transclude: 'element',replace: true,

上面的保留了hello,hello是cust的子元素,如果我想把cust也保留嵌入模板该怎么做,你或许说把replace改为false不就保留了.这样是可以保留,但跟我要说的不一样.

如果我把body改成<label cust>hello</label>,我想保留label该怎么做,现在只能把hello嵌入模板.

所以接下来要说的就是transclude:'element',把子元素和本身都保留下来.

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



可以看到label保留下来了.

d.transclude: 'element',replace:

false


下面最后一个比较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是关键.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息