参考来源:彻底弄懂AngularJS中的transclusion

对以上文章进行摘录、总结和测试记录

在使用指令的时候,如果想要使用指令中的子元素,那么你就要用transclusion。

指令的DDO中,transclude有三个值: transclude: false |true | 'element' ;第一个是默认值,后两个有什么区别呢?

transclude:'element'

//TODO

transclude:true

<body ng-app="app">
<dx>
这是子元素
</dx>
</body>
<script>
var app = angular.module('app',[]);
app.directive('dx',function() {
return {
transclude:true,
template:'<div> 1233 <div ng-transclude></div> </div>'
}
});
</script>

运行结果:子元素会被嵌入进 <div ng-transclude></div> 里,而且拥有自己的作用域【后面会讲到这个作用域用来干嘛的】

可以发现,模板中的ng-tranclude决定了在什么地方放置嵌入部分。

以上仅仅只是嵌入了一次,如果我希望多次嵌入,怎么办?

在代码中使用transclude。如下:

link函数的第五个参数、compile函数的第三个参数、依赖注入的$transclude。三者用法一致(前两种用法中要求必须在DDO中打开transclude,如transclude:true,否则获取到的transclude为undefined)。以link为例:

1.执行transclude函数,获取子元素

<body ng-app="app">
<dx>
这是子元素
</dx>
</body>
<script>
var app = angular.module('app',[]);
app.directive('dx',function() {
return {
transclude:'true',
link:function(scope,ele,sttr,ctrl,transclude){
var sub = transclude();
for(var i = 0;i<3;i++){
ele.append(sub.clone());
}
}
}
});

运行结果如下,测试过程中发现在for循环运行之前,dx中的子元素被清空了,

2.给transclude传递两个参数

将以上案例修改如下:

 app.directive('dx',function() {
return {
transclude:'true',
link:function(scope,ele,sttr,ctrl,transclude){
transclude(scope,function(sub){
for(var i = 0;i<3;i++){
ele.append(sub.clone());
}
});
}
}
});

运行效果没有发生任何变化。第二个参数中的sub,也还是当前指令的子元素。

上面说过获取到的子元素都是有自己的作用域,第一个参数scope是这个子元素的上下文环境,子元素的作用域会继承这个上下文环境。

例子:

<body ng-app="app">
这是外部的name:{{name}}
<dx>
这是我自定义的:{{name}}
</dx>
</body>
<script>
var app = angular.module('app',[]);
app.directive('dx',function() {
return {
transclude:'true',
link:function(scope,ele,sttr,ctrl,transclude){
scope.name = 7777;
var myScope = scope.$new();
myScope.name = 1233;
transclude(myScope,function(sub){
ele.append(sub);
});
}
}
});
</script>

运行结果:这是外部的name:7777 这是我自定义的:1233

以上通过new从当前的作用域中衍生出一个新的作用域(新的作用域继承自当前作用域)。然后对新的作用域进行数据修改,最后应用到子元素上。


对获取到的子元素进行进一步理解:

<dx>
这是我自定义的:{{name}}
</dx>
</body>
<script>
var app = angular.module('app',[]);
app.directive('dx',function() {
return {
transclude:'true',
link:function(scope,ele,sttr,ctrl,transclude){
var myScope = scope.$new();
myScope.name = 1233;
transclude(myScope,function(sub){
for(var i = 0;i<3;i++){
ele.append(sub.clone());
}
});
}
}
});
</script>

运行结果:这是我自定义的:{{name}} 这是我自定义的:{{name}} 这是我自定义的:{{name}}

显然这不是我们想要的,而且为什么会出现这样的结果?

因为我们在循环中添加的只是克隆体,或者直接理解为添加的仅仅是一坨html而已,这和angular没有任何关系,自然也就不存在数据绑定的说法,所以文本就直接显示出来了。

解决办法就是让这一坨html与angular扯上关系,进行手动编译,注入$compile服务,然后修改循环如下:

                transclude(scope,function(sub){
for(var i = 0;i<3;i++){
var clone = sub.clone();
$compile(clone)(myScope);
ele.append(clone);
}
});

以上transclude的第一个scope实际上已经没用了,因为手动编译的时候,我们指定了这个被编译元素的上下文,编译过程就会只读取这个上下文了。

总结:transclude的第一个scope仅仅针对sub本身是有用的,而对于sub的克隆体来说没有任何用处

angularJS transclude的更多相关文章

  1. angularjs transclude demo

    <!doctype html> <html lang="en" ng-app="expanderModule"> <head> ...

  2. [AngularJS] Transclude -- using what existing in DOM to replace the template elements in directive

    var app = angular.module("phoneApp", []); app.controller("AppCtrl", function($sc ...

  3. AngularJS transclude 理解及例子

    一.概念理解 transclude可以在指令中让使用者自定义模板,也就是说,指令中模板的一部分,让指令的使用者动态指定:与指定中的Scope属性值为{}时候的作用类似,scope属性让指令使用者动态制 ...

  4. angularjs指令参数transclude

    angularjs指令参数transclude transclude翻译为嵌入,和之前看到的vue中的slots作用差不多,目的是将指令元素的子内容嵌入到指令的模板中 定义指令 <div sid ...

  5. AngularJs directive 'transclude' option 详解

    transclude好像不是一个英语单词,有道词典里没有,百度翻译的意思是嵌入. transclude在angularjs的自定义的derective中是比较常见的一个东西,所有有必要要了解它. 我们 ...

  6. angularjs作用域之transclude

    transclude是一个可选的参数.如果设置了,其值必须为true,它的默认值是false.嵌入有时被认为是一个高级主题,但某些情况下它与我们刚刚学习过的作用域之间会有非常好的配合.使用嵌入也会很好 ...

  7. 浅析AngularJS自定义指令之嵌入(transclude)

    AngularJS自定义指令的嵌入功能与vue的插槽十分类似,都可以实现一些自定义内容展现.在开始之前先简单介绍下自定义指令的transclude属性和AngularJS的内置指令ng-transcl ...

  8. AngularJs 中的transclude的理解

    Transclude是一个配置, 为了告诉AngularJs去获取当前指令模版内部的所有内容(实际使用ng-transclude), 更多关于怎么创建一个包含其他元素的指令: documentatio ...

  9. AngularJS中transclude用法详解

    这篇文章主要介绍了AngularJS中transclude用法,详细分析了transclude的具体功能.使用技巧与相关注意事项,需要的朋友可以参考下 本文实例讲述了AngularJS中transcl ...

随机推荐

  1. Spring Security 使用Ajax登陆无法跳转页面解决方法

    使用Security的朋友都知道,使用Security后,不再需要我们自己过多的(还需要写少量代码)写登陆的逻辑,只需要自己在html的登陆表单上面定义好输入框name为:username和passw ...

  2. PHP gd 库添加 freetype

    gd 库未安装 freetype 可能导致验证码图片加载不出来等问题. 先到 PHP 的扩展目录里面找到 gd 扩展文件夹 最好先 make clean 清除之前编译的可执行文件及配置文件,运行/us ...

  3. 微信小程序红包开发 小程序发红包 开发过程中遇到的坑 微信小程序红包接口的

    微信小程序红包开发 小程序发红包 开发过程中遇到的坑 微信小程序红包接口的   最近公司在开发一个小程序红包系统,客户抢到红包需要提现.也就是通过小程序来给用户发红包. 小程序如何来发红包呢?于是我想 ...

  4. htm5 + ajax 文件上传

    好文 http://www.cnblogs.com/morlin/p/4930822.html 后台接收 FormData 的参数一直为空,将jquery改为最高版本,问题解决.测试发现IE10以上才 ...

  5. SpringCloud开发学习总结(七)—— 声明式服务调用Feign(二)

    参数绑定 在上一章的示例中,我们使用Spring Cloud Feign实现的是一个不带参数的REST服务绑定.然而现实系统中的各种业务接口要比它复杂得多,我们有时会在HTTP的各个位置传入各种不同类 ...

  6. Super Mario 树状数组离线 || 线段树

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  7. CentOS 7不重启刷新磁盘列表

    [root@master-09:29:09 33~]#ls /sys/class/scsi_host/host0 host1 host2[root@master-09:29:55 34~]#echo ...

  8. eclipse 闪退原因

    电脑关机后 重启发现eclipse竟然打不开了,打开出现闪退,原因是: 1.JDK版本不一致,或者你电脑上安装了多个版本: 2.环境变量:安装了其他软件比如:oracle 它自带有一个较低版本的JDK ...

  9. AJPFX对选择和冒泡两种排序的理解

    冒泡排序和直接选择排序都是排序中比较简单和容易实现的算法,先简单说说两者的区别:先以按照元素从小到大为:冒泡排序:将相邻元素两两比较,如果有比较大的,就把比较大的放在右边,这样的结果就是一轮排序完毕后 ...

  10. ubuntu安装mysql多实例

    想要尝试mysql的读写分离,在云上安装完mysql之后突然想到一个问题:我本机是没有公网IP的. 开始尝试在唯一一台云服务器上安装多个mysql实例. 主要步骤: 1.新建MySQL目录 (1):新 ...