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 相关文章推荐
自适应图片大小的弹出窗口
Jul 27 Javascript
Extjs Ext.MessageBox.confirm 确认对话框详解
Apr 02 Javascript
javascript实现客户端兼容各浏览器创建csv并下载的方法
Mar 23 Javascript
bootstrap实现弹窗和拖动效果
Jan 03 Javascript
AngularJS实现单独作用域内的数据操作
Sep 05 Javascript
浅析javascript中的Event事件
Dec 09 Javascript
Vue.js中用webpack合并打包多个组件并实现按需加载
Feb 17 Javascript
微信小程序图片横向左右滑动案例
May 19 Javascript
Vue通过配置WebSocket并实现群聊功能
Dec 31 Javascript
jquery检测上传文件大小示例
Apr 26 jQuery
Vue.extend 登录注册模态框的实现
Dec 29 Vue.js
Vue多选列表组件深入详解
Mar 02 Vue.js
浅谈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
索尼ICF-SW100收音机评测
2021/03/02 无线电
thinkphp中session和cookie无效的解决方法
2014/12/19 PHP
搜索附近的人PHP实现代码
2018/02/11 PHP
ASP SQL防注入的方法
2008/12/25 Javascript
Domino中运用jQuery读取视图内容的方法
2009/10/21 Javascript
在html页面上拖放移动标签
2010/01/08 Javascript
JavaScript 输入框内容格式验证代码
2010/02/11 Javascript
无缝滚动js代码通俗易懂(自写)
2013/06/19 Javascript
jQuery ajax dataType值为text json探索分享
2013/09/23 Javascript
jQuery实现首页顶部可伸缩广告特效代码
2015/04/15 Javascript
常用的Javascript设计模式小结
2015/12/09 Javascript
jQuery中$.ajax()方法参数解析
2016/10/22 Javascript
JS判断指定dom元素是否在屏幕内的方法实例
2017/01/23 Javascript
关于express与koa的使用对比详解
2018/01/25 Javascript
vue移动端实现下拉刷新
2018/04/22 Javascript
vue实现引入本地json的方法分析
2018/07/12 Javascript
浅析Vue项目中使用keep-Alive步骤
2018/07/27 Javascript
Angular2使用SVG自定义图表(条形图、折线图)组件示例
2019/05/10 Javascript
微信小程序实现吸顶特效
2020/01/08 Javascript
Jquery如何使用animation动画效果改变背景色的代码
2020/07/20 jQuery
python获取各操作系统硬件信息的方法
2015/06/03 Python
Python音频操作工具PyAudio上手教程详解
2019/06/26 Python
如何通过python的fabric包完成代码上传部署
2019/07/29 Python
PYTHON绘制雷达图代码实例
2019/10/15 Python
python学生信息管理系统实现代码
2019/12/17 Python
解决Tensorboard 不显示计算图graph的问题
2020/02/15 Python
对pytorch的函数中的group参数的作用介绍
2020/02/18 Python
html5实现图片转圈的动画效果——让页面动起来
2017/10/16 HTML / CSS
澳大利亚便宜隐形眼镜购买网站:QUICKLENS Australia
2018/10/06 全球购物
物业管理计划书
2014/01/10 职场文书
出纳会计岗位职责
2014/03/12 职场文书
学风建设演讲稿
2014/09/12 职场文书
2015年公务员个人工作总结
2015/04/24 职场文书
关于迟到的检讨书
2015/05/06 职场文书
《鲁滨逊漂流记》之六读后感(4篇)
2019/09/29 职场文书
spring cloud eureka 服务启动失败的原因分析及解决方法
2022/03/17 Java/Android