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 相关文章推荐
JS写的贪吃蛇游戏(个人练习)
Jul 08 Javascript
jQuery使用removeClass方法删除元素指定Class的方法
Mar 26 Javascript
JavaScript函数内部属性和函数方法实例详解
Mar 17 Javascript
js前端面试题及答案整理(一)
Aug 26 Javascript
Bootstrap幻灯片轮播图支持触屏左右手势滑动的实现方法
Oct 13 Javascript
微信小程序去哪里找 小程序到底如何使用(附小程序名单)
Jan 09 Javascript
JS失效 提示HTML1114: (UNICODE 字节顺序标记)的代码页 utf-8 覆盖(META 标记)的冲突的代码页 utf-8
Jun 23 Javascript
Vue.js在数组中插入重复数据的实现代码
Nov 17 Javascript
vue cli 3.x 项目部署到 github pages的方法
Apr 17 Javascript
DWR内存兼容及无法调用问题解决方案
Oct 16 Javascript
ES6中的类(Class)示例详解
Dec 09 Javascript
js实现鼠标切换图片(无定时器)
Jan 27 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
PHP5中虚函数的实现方法分享
2011/04/20 PHP
php的chr和ord函数实现字符加减乘除运算实现代码
2011/12/05 PHP
PHP+MySQL投票系统的设计和实现分享
2012/09/23 PHP
php Imagick获取图片RGB颜色值
2014/07/28 PHP
PHP基于redis计数器类定义与用法示例
2018/02/08 PHP
掌握PHP垃圾回收机制详解
2019/03/13 PHP
IE/FireFox具备兼容性的拖动代码
2007/08/13 Javascript
JavaScript实现页面滚动图片加载(仿lazyload效果)
2011/07/22 Javascript
AngularJS学习笔记之基本指令(init、repeat)
2015/06/16 Javascript
果断收藏9个Javascript代码高亮脚本
2016/01/06 Javascript
RequireJS使用注意细节
2016/05/15 Javascript
javascript数组遍历的方法实例分析
2016/09/13 Javascript
详解ionic本地相册、拍照、裁剪、上传(单图完全版)
2017/10/10 Javascript
Vue+SpringBoot开发V部落博客管理平台
2017/12/27 Javascript
js生成word中图片处理方法
2018/01/06 Javascript
Vue中使用webpack别名的方法实例详解
2018/06/19 Javascript
JavaScript插入排序算法原理与实现方法示例
2018/08/06 Javascript
小白教程|一小时上手最流行的前端框架vue(推荐)
2019/04/10 Javascript
基于JS实现前端压缩上传图片的实例代码
2019/05/14 Javascript
Vue 实现分页与输入框关键字筛选功能
2020/01/02 Javascript
react 生命周期实例分析
2020/05/18 Javascript
[05:15]2018年度CS GO社区贡献奖-完美盛典
2018/12/16 DOTA
详解Python中的变量及其命名和打印
2016/03/11 Python
Python探索之ModelForm代码详解
2017/10/26 Python
python导出hive数据表的schema实例代码
2018/01/22 Python
在Pycharm中修改文件默认打开方式的方法
2019/01/17 Python
Python动态赋值的陷阱知识点总结
2019/03/17 Python
Python API 自动化实战详解(纯代码)
2019/06/11 Python
python+requests接口压力测试500次,查看响应时间的实例
2020/04/30 Python
Python中三维坐标空间绘制的实现
2020/09/22 Python
Pytest测试框架基本使用方法详解
2020/11/25 Python
10个python爬虫入门基础代码实例 + 1个简单的python爬虫完整实例
2020/12/16 Python
采购人员的个人自我评价
2014/01/16 职场文书
2014年党课学习材料
2014/05/11 职场文书
北京故宫导游词
2015/01/31 职场文书
2015年医院工作总结范文
2015/04/09 职场文书