你的位置:首页 > 软件开发 > Java > angular高级篇之transclude使用详解

angular高级篇之transclude使用详解

发布时间:2017-09-20 10:00:22
angular指令的transclude属性是一个让初学者比较难以理解的地方,transclude可以设置为false(默认),true或者对象三种值,如果不设该属性就默认为false,也就是说你不需要将该指令所在元素包含的内容嵌入到模板中。当transclude为true的时候 ...

angular指令的transclude属性是一个让初学者比较难以理解的地方,transclude可以设置为false(默认),true或者对象三种值,如果不设该属性就默认为false,也就是说你不需要将该指令所在元素包含的内容嵌入到模板中。

当transclude为true的时候,这时指令所在元素包含的内容会被嵌入到模板中有ng-transclude指令的元素中,例如:

index.html

<!DOCTYPE html><html ng-app="myapp"><head> <meta charset="utf-8"> <title>angular test</title></head><body ng-controller="myCtrl"> <div hello="{{name}}">你好</div></body><script src='/images/loading.gif' data-original="./node_modules/angular/angular.js"></script><script src='/images/loading.gif' data-original="./index.js"></script></html>

index.js

let app = angular.module('myapp',[]);app.controller('myCtrl', $scope =>{ $scope.name = "Jhon";});app.directive('hello', () =>{ return {  restrict: 'A',  template: '<div><span ng-transclude></span>{{name}}</div>',  transclude: true,  scope:{   name: "@hello"  } }});

运行之后的效果如下:

<div hello="Jhon" class="ng-isolate-scope"> <div class="ng-binding">  <span ng-transclude="">你好</span>  Jhon </div></div>

当指令元素包含的内容需要嵌入到指令模板不同地方的时候,这个时候就要把transclude设置为对象,例如下面这个我在项目中使用的一个例子:

index.html

<!DOCTYPE html><html ng-app="myapp"><head> <meta charset="utf-8"> <title>angular test</title></head><body ng-controller="myCtrl"> <panel>  <panel-header>{{title}}</panel-header>  <panel-body>{{content}}</panel-body>  <panel-footer>{{footer}}</panel-footer> </panel></body><script src='/images/loading.gif' data-original="./node_modules/angular/angular.js"></script><script src='/images/loading.gif' data-original="./index.js"></script></html>

index.js

let app = angular.module('myapp',[]);app.controller('myCtrl', ['$scope', $scope =>{ $scope.title = "标题"; $scope.content = "内容"; $scope.footer = "页脚";}]);app.directive('panel', () =>{ return {  restrict: 'E',  replace: true,  transclude: {   'header': '?panelHeader',   'body': 'panelBody',   'footer': '?panelFooter'  },  template: `   <div >    <div ng-transclude="header"></div>    <div ng-transclude="body"></div>    <div ng-transclude="footer"></div>   </div>` }});

显示结果如下:

<div class="panel"> <div class="panel-header" ng-transclude="header">  <panel-header class="ng-binding ng-scope">   标题  </panel-header> </div> <div class="panel-body" ng-transclude="body">  <panel-body class="ng-binding ng-scope">   内容  </panel-body> </div> <div class="panel-footer" ng-transclude="footer">  <panel-footer class="ng-binding ng-scope">   页脚  </panel-footer> </div></div>

这里指令元素内部有三个指令,这三个指令必须以E的形式调用,它们分别要插入到模板的不同位置,tranclude指定了要插入的位置,transclude是一个键值对的对象,key指定了要插入模板的位置,value就是要插入的内容,?代表这个嵌入点不一定有指令存在,否则必须在这个点插入指令,不然会报错。

值得注意的是,这个实例也证明了一点,指令包含的元素的作用域继承自指令的父作用域而不是隔离作用域。

 

除了使用ng-transclude指令指定内容嵌入的地方外,我们还有两种方法可以做到这点。

第一种就是在控制器中使用$transclude服务,例如以下代码:

index.html

<!DOCTYPE html><html ng-app="myapp"><head> <meta charset="utf-8"> <title>angular test</title></head><body ng-controller="myCtrl"> <hello name="{{name}}"><span>{{action}}</span></hello></body><script src='/images/loading.gif' data-original="./node_modules/angular/angular.js"></script><script src='/images/loading.gif' data-original="./index.js"></script></html>

index.js

let app = angular.module('myapp',[]);app.controller('myCtrl', ['$scope', $scope =>{ $scope.name = "Jhon"; $scope.action = "你好";}]);app.directive('hello', () =>{ return {  restrict: 'E',  transclude: true,  controller: ['$scope', '$element', '$transclude', ($scope, $element, $transclude) =>{   $transclude(clone =>{    //$element.find只能通过标签名进行查找    $element.find('span').append(clone);   });  }],  template: '<div><span></span>{{name}}</div>',  scope: {   name: '@'  } }});

最后显示的结果如下:

<hello name="Jhon" class="ng-isolate-scope"> <div class="ng-binding">  <span>   <span class="ng-binding ng-scope">    你好   </span>  </span>  Jhon </div></hello>

其中控制器中的$element就是编译了之后的模板,而$transclude中的参数clone则是被编译了的指令包含的内容。两者可以同时对模板和内容进行处理。

 

另一种方法是在compile中指定第三个transcludeFn参数,如下所示:

 index.js

let app = angular.module('myapp',[]);app.controller('myCtrl', ['$scope', $scope =>{ $scope.name = "Jhon"; $scope.action = "你好";}]);app.directive('hello', () =>{ return {  restrict: 'E',  transclude: true,  compile: (tElement, tAttrs, transcludeFn) =>{   return (scope, element, attrs) =>{    scope.action = "hello";    transcludeFn(scope, (clone) =>{     element.find('span').append(clone);    });   };  },  template: '<div><span></span>{{name}}</div>',  scope: {   name: '@'  } }});

这个文件实现了以上控制器中相同的功能,transcludeFn接受两个参数,一个scope作用域,一个函数,和controller一样,这个函数的参数clone就是编译之后的要嵌入的内容。唯一不同的是,编译这个clone的作用域是传进去的第一个参数,而controller中clone是继承了指令的父作用域。

 

原标题:angular高级篇之transclude使用详解

关键词:

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

可能感兴趣文章

我的浏览记录