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


Posted in Javascript onOctober 24, 2016

我们使用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节点的区别了

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

看完上面的图,你可以明显的区别到两者对DOM的克隆不一样的,另外如果在声明属性为‘element'时,需要声明replace为true,才能渲染出来。我查了很多资料,最终用断点得出了我认为对的结论,断点追踪的结果是发现如果不声明replace,好像就不会执行ngTransclude指令,这点我很奇怪,正因为这样子所以导致没有成功渲染。二归根结底其实是两者的操作的DOM元素不同,在声明transclude为element时,replace为true,你取到的DOM节点是含有transclude属性的节点(子节点),而为false你拿到的并不是含有transclude属性的节点(父节点),而ng本身不对其节点进行遍历,导致没能执行ngTransclude指令

我看到一个观点觉得不错,大概意思就是:源于功能的考虑,在使用element属性的时候,一般都是起占位符的作用,你需要做的操作是对DOM的添加时候,才会用到这个克隆功能。

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

以上就是小编为大家带来的angularJs关于指令的一些冷门属性详解全部内容了,希望大家多多支持三水点靠木~

Javascript 相关文章推荐
使用jquery给input和textarea设定ie中的focus
May 29 Javascript
一步一步教你写一个jQuery的插件教程(Plugin)
Sep 03 Javascript
奉献给JavaScript初学者的编写开发的七个细节
Jan 11 Javascript
EXTJS FORM HIDDEN TEXTFIELD 赋值 使用value不好用的问题
Apr 16 Javascript
JavaScript中的数据类型转换方法小结
Oct 26 Javascript
动态生成的DOM不会触发onclick事件的原因及解决方法
Aug 06 Javascript
jquery购物车结算功能实现方法
Oct 29 Javascript
vue最简单的前后端交互示例详解
Oct 11 Javascript
axios 实现post请求时把对象obj数据转为formdata
Oct 31 Javascript
vue 使用插槽分发内容操作示例【单个插槽、具名插槽、作用域插槽】
Mar 06 Javascript
vue 封装 Adminlte3组件的实现
Mar 18 Javascript
详解如何使用Node.js实现热重载页面
May 06 Javascript
浅谈Angular中ngModel的$render
Oct 24 #Javascript
Javascript vue.js表格分页,ajax异步加载数据
Oct 24 #Javascript
H5移动端适配 Flexible方案
Oct 24 #Javascript
javascript的document中的动态添加标签实现方法
Oct 24 #Javascript
Ajax+FormData+javascript实现无刷新表单信息提交
Oct 24 #Javascript
利用JS实现点击按钮后图片自动切换的简单方法
Oct 24 #Javascript
express文件上传中间件Multer详解
Oct 24 #Javascript
You might like
PHP初学者头疼问题总结
2006/07/08 PHP
一个简洁的多级别论坛
2006/10/09 PHP
php连接数据库代码应用分析
2011/05/29 PHP
PHP处理excel cvs表格的方法实例介绍
2013/05/13 PHP
探讨如何在php168_cms中提取验证码
2013/06/08 PHP
利用PHP函数计算中英文字符串长度的方法
2014/11/11 PHP
JavaScript中的一些定位属性[图解]
2010/07/14 Javascript
js 上传图片预览问题
2010/12/06 Javascript
合并table相同单元格的jquery插件分享(很精简)
2011/06/20 Javascript
js或者jquery判断图片是否加载完成实现代码
2013/03/20 Javascript
JavaScript数据绑定实现一个简单的 MVVM 库
2016/04/08 Javascript
JavaScript中各种引用类型的常用操作方法小结
2016/05/05 Javascript
详解如何使用Node.js编写命令工具——以vue-cli为例
2017/06/29 Javascript
node.js实现微信JS-API封装接口的示例代码
2017/09/06 Javascript
vue.js整合mint-ui里的轮播图实例代码
2017/12/27 Javascript
JavaScript EventEmitter 背后的秘密 完整版
2018/03/29 Javascript
微信小程序实现之手势锁功能实例代码
2018/07/19 Javascript
vue 中Virtual Dom被创建的方法
2019/04/15 Javascript
微信小程序整合使用富文本编辑器的方法详解
2019/04/25 Javascript
VUE实现密码验证与提示功能
2019/10/18 Javascript
[51:53]完美世界DOTA2联赛循环赛 LBZS vs DM BO2第二场 11.01
2020/11/02 DOTA
Django中的“惰性翻译”方法的相关使用
2015/07/27 Python
使用Python内置的模块与函数进行不同进制的数的转换
2016/03/12 Python
windows系统下Python环境的搭建(Aptana Studio)
2017/03/06 Python
Pycharm 设置自定义背景颜色的图文教程
2018/05/23 Python
Python Django实现layui风格+django分页功能的例子
2019/08/29 Python
Python3如何判断三角形的类型
2020/04/12 Python
Python远程方法调用实现过程解析
2020/07/28 Python
浅谈Html5移动端ios/Android兼容性总结
2018/06/01 HTML / CSS
欧舒丹比利时官网:L’OCCITANE比利时
2017/04/25 全球购物
世嘉游戏英国官方商店:SEGA Shop UK
2019/09/20 全球购物
Jowissa官方网站:瑞士制造的手表,优雅简约的设计
2020/07/29 全球购物
揠苗助长教学反思
2014/02/04 职场文书
《追风筝的人》:人心中的成见是座大山,但请不忘初心
2019/11/15 职场文书
25句企业管理语录:助你迅速打开思路,句句经典!
2020/01/14 职场文书
APP界面设计技巧和注意事项
2022/04/29 杂记