angularJs关于指令的一些冷门属性

  我们使用ng的时候,经常会使用到指令,大家所熟知的属性我在这里就不介绍了,讲讲大家没怎么留意的属性

  1.multiElement

    这是指定指令作用区间的功能,最常用的就是ng-repeat-start和ng-repeat-end了。

  2.priority

    指令优先级,优先级越高,指令越早执行。

  3.terminal

    是否允许优先级低的指令起作用,如果是true,那么只有比当前指令或跟当前指令等级相同的指令才可以执行。最典型的就是ngIf

  4.templateNamespace

    声明模板的格式有三种选择 svg、html、math

  5.transclude

    或许有人疑问了,transclude也算是冷门属性吗?其实大家对transclude了解并没有想象的那么深,transclude是一个挺复杂的属性,一般大家会用到的也仅仅是true,false。这两个属性我在这里就不讲了,在这里我主要讲的是transclude:element,我google了一整天都没找到正确描述这个属性的方法。我觉得google出来的答案太文档化了。最后在研究$transclude才看出来这个属性的功能究竟在哪里。再讲功能前我们先了解下$transclude

    无论在指令的compile还是link时期我们的最后一个参数就是$transclude了,这里其实我们看看源码是如何定义的,我看的源码是ng1.5.3的    

function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement, slotName) {
          var transcludeControllers;
          // No scope passed in:
          if (!isScope(scope)) {
            slotName = futureParentElement;
            futureParentElement = cloneAttachFn;
            cloneAttachFn = scope;
            scope = undefined;
          }

          if (hasElementTranscludeDirective) {
            transcludeControllers = elementControllers;
          }
          if (!futureParentElement) {
            futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;
          }
          if (slotName) {
            // slotTranscludeFn can be one of three things:
            //  * a transclude function - a filled slot
            //  * `null` - an optional slot that was not filled
            //  * `undefined` - a slot that was not declared (i.e. invalid)
            var slotTranscludeFn = boundTranscludeFn.$$slots[slotName];
            if (slotTranscludeFn) {
              return slotTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
            } else if (isUndefined(slotTranscludeFn)) {
              throw $compileMinErr(‘noslot‘,
               ‘No parent directive that requires a transclusion with slot name "{0}". ‘ +
               ‘Element: {1}‘,
               slotName, startingTag($element));
            }
          } else {
            return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
          }
        }

还有一个另一个函数要特别指出来,就是最后返回的 boundTranscludeFn 这个方法,下面是他的源码

function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
      function boundTranscludeFn(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {

        if (!transcludedScope) {
          transcludedScope = scope.$new(false, containingScope);
          transcludedScope.$$transcluded = true;
        }

        return transcludeFn(transcludedScope, cloneFn, {
          parentBoundTranscludeFn: previousBoundTranscludeFn,
          transcludeControllers: controllers,
          futureParentElement: futureParentElement
        });
      }

这两个方法到底是在做什么呢?其实就是克隆了当前指令的节点,并生成子作用域。克隆的节点由transclude定义,如果你的属性是true,则克隆的是指令模板中的ng-transclude所在的DOM节点,及其子节点。如果属性是element则克隆整个模板的节点。

这是两个指令的代码

 angular.module(‘MyApp‘, [])
            .directive(‘dropPanel‘, function() {
                return {
                    transclude: ‘element‘,
                    replace: true,
                    template: "<div class=‘drop-panel‘>" +
                        "<span ng-transclude class=‘111‘></span>" +
                        "</div>",
                    link: function(scope, el, c, d, $transclude) {
                        $transclude(function ngRepeatTransclude(clone, scope) {
                            console.log(clone);
                        })

                    }
                }
            })
            .directive(‘dropPanel2‘, function() {
                return {
                    transclude: true,
                    replace: true,
                    template: "<div class=‘drop-panel‘>" +
                        "<span ng-transclude class=‘111‘></span>" +
                        "</div>",
                    link: function(scope, el, c, d, $transclude) {
                        $transclude(function ngRepeatTransclude(clone, scope) {
                            console.log(clone);
                        })
                    }
                }
            })

如果你觉得replace干扰了对结果的理解,你可以注释掉,然后查看控制台中打印出来的clone,你就能知道所谓transclude的属性声明为element的作用了,我们打开replace目的在于能较清楚的查看DOM节点,来获得结论,下面就是两者编译后DOM节点的区别了

  看完上面的图,你可以明显的区别到两者对DOM的克隆不一样的,另外如果在声明属性为‘element’时,需要声明replace为true,才能渲染出来。我查了很多资料,但是还是没能力为大家解答这个问题,断点追踪的结果是发现如果不声明replace,好像就不会执行ngTransclude指令,这点我很奇怪,正因为这样子所以导致没有成功选人。但是我看到一个观点觉得不错,大概意思就是:源于功能的考虑,在使用element属性的时候,一般都是起占位符的作用,你需要做的操作是对DOM的添加时候,才会用到这个克隆功能。

  我觉得这个观点不错,看过很多关于ngrepeat的介绍,很多文章都说ngrepeat源码是通过$scope.$new()来生成子作用域的,实际上并不完全正确,他的确是通过$scope.$new产生子作用域的,但是这个产生功能是交给$transclude函数去做得,实际上ngrepeat的源码上是通过$transclude来生成子作用域和添加DOM节点的。与上面的观点有相似之处。

  就讲到这里了,这是作者原创,转载请注明

时间: 2024-11-10 01:19:40

angularJs关于指令的一些冷门属性的相关文章

学习AngularJs:Directive指令用法(完整版)

这篇文章主要学习AngularJs:Directive指令用法,内容很全面,感兴趣的小伙伴们可以参考一下 本教程使用AngularJs版本:1.5.3 AngularJs GitHub: https://github.com/angular/angular.js/ AngularJs下载地址:https://angularjs.org/ 摘要:Directive(指令)笔者认为是AngularJ非常强大而有有用的功能之一.它就相当于为我们写了公共的自定义DOM元素或LASS属性或ATTR属性,并

AngularJS之指令

紧接上篇博客“初探AngularJS” 一.前言 在AngularJS中指令尤为重要且内容庞多,固单独提炼出来,梳理一番.如有错误,请不吝讲解. 好了,言归正传,让我们一起走进Angular指令的世界. 在上篇博客的前言部分提到,Angular的核心就是对HTML标签的增强.我们用到的诸如ng-app.ng-controller等等这些都是属于Angular指令,具体点,它们为Angular内置的指令. Angular不仅提供了内置指令,它还允许我们自定义指令,不然Angular就太low咯.

Angularjs 事件指令 input 相关指令 和样式指令 DOM 操作指令详解

Angularjs 事件指令 input 相关指令 和样式指令DOM 操作指令详解学习要点:1. AngularJs 事件指令2. input 相关指令3. 样式指令4. DOM 操作指令5. ngBind/ngBindHtml/ngBindTemplate 重点6. ng-init ng-mode ng-model-options ng-controler 1. Angularjs 事件指令自己研究:ng-click/dbclickng-mousedown/upng-mouseenter/le

AngularJS ng-model 指令

AngularJS ng-model 指令 ng-model 指令用于绑定应用程序数据到 HTML 控制器(input, select, textarea)的值. <div ng-app="myApp" ng-controller="myCtrl">名字: <input ng-model="name"></div><script>var app = angular.module('myApp', [

跟我学AngularJs:Directive指令用法解读(下)

此文接 跟我学AngularJs:Directive指令用法解读(上) 8.transclude 如果不想让指令内部的内容被模板替换,可以设置这个值为true.一般情况下需要和ngTransclude指令一起使用. 比如:template:"<div>hello every <div ng-transclude></div></div>",这时,指令内部的内容会嵌入到ng-transclude这个div中.也就是变成了<div>

跟我学AngularJs:Directive指令用法解读(上)

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 本教程使用AngularJs版本:1.5.3 AngularJs GitHub: https://github.com/angular/angular.js/ AngularJs下载地址:https://angularjs.org/ 摘要: Directive(指令)笔者认为是AngularJ非常强大而有有用的功能之一.它就相当于为我们写了公共的自定义DOM元素或CLASS属性或ATTR属性

AngularJS 事件指令/input相关指令/样式指令/DOM操作指令详解

1.AngularJS 事件指令 (1)ng-click 鼠标点击事件 [html] <button ng-click="count = count + 1" ng-init="count=0"> Increment  </button> <span>  count: {{count}}  </span> (2)ng-dblclick 鼠标双击事件 [html] <button ng-dblclick="

angularJs之指令详解(一)

指令(Directives)是所有AngularJS应用最重要的部分.尽管AngularJS已经提供了非常丰富的指令,但还是经常需要创建应用特定的指令.这篇教程会为你讲述如何自定义指令,以及介绍如何在实际项目中使用.在这篇文章的最后(第二部分),我会指导你如何使用Angular指令来创建一个简单的记事本应用. 概述 一个指令用来引入新的HTML语法.指令是DOM元素上的标记,使元素拥有特定的行为.举例来说,静态的HTML不知道如何来创建和展现一个日期选择器控件.让HTML能识别这个语法,我们需要

带你走近AngularJS - 体验指令实例

带你走近AngularJS系列: 带你走近AngularJS - 基本功能介绍 带你走近AngularJS - 体验指令实例 带你走近AngularJS - 创建自定义指令 ------------------------------------------------------------------------------------------------ 之前我们已经介绍了所有的AngularJS 基础知识,下面让我们通过实例来加深记忆,体验自定义指令的乐趣. 手风琴指令 我们展示的第