AngularJS中transclude用法详解(2)

虽然这种方法达到了我们的目的,但是允许默认的transclude操作,然后再人工的从DOM元素中移出不是非常有效率的。因此,我们有了compile函数中的transclude参数和控制器中的$transclude服务

编译函数参数中的transclude

开发者指南中给了我们以下的关于指令中编译函数的形式:

function compile(tElement, tAttrs, transclude) { ... }

其中关于第三个参数transclude的解释是:

transclude - A transclude linking function: function(scope, cloneLinkingFn).

好的,现在我们利用这个函数来实现我们刚才讲到的功能,从而不需要再先暂存内容,然后再插入到其他地方。

在fiddle中查看例子:

<div ng-controller="parentController"> <button-bar> <button ng-click="onPrimary1Click()">{{primary1Label}}</button> <button>Primary2</button> <button>Secondary1</button> </button-bar> </div>

JS:

var testapp = angular.module('testapp', []); testapp.controller('parentController', ['$scope', '$window', function($scope, $window) { $scope.primary1Label = 'Prime1'; $scope.onPrimary1Click = function() { $window.alert('Primary 1 clicked'); } }]); testapp.directive('primary', function() { return { restrict: 'C', link: function(scope, element, attrs) { element.addClass('btn btn-primary'); } } }); testapp.directive('secondary', function() { return { restrict: 'C', link: function(scope, element, attrs) { element.addClass('btn'); } } }); testapp.directive('buttonBar', function() { return { restrict: 'EA', template: '<div><div></div><div></div></div>', replace: true, transclude: true, compile: function(elem, attrs, transcludeFn) { return function (scope, element, attrs) { transcludeFn(scope, function(clone) { var primaryBlock = elem.find('div.primary-block'); var secondaryBlock = elem.find('div.secondary-block'); var transcludedButtons = clone.filter(':button'); angular.forEach(transcludedButtons, function(e) { if (angular.element(e).hasClass('primary')) { primaryBlock.append(e); } else if (angular.element(e).hasClass('secondary')) { secondaryBlock.append(e); } }); }); }; } }; });

注意到,transcludeFn函数需要一个可用的scope作为第一个参数,但是编译函数中没有可用的scope,所以这里需要在链接函数中执行transcludeFn。这种方法实际上是在link函数中同时操作编译后的DOM元素和模板元素(主要是因为transcludeFn函数中保存着指令的内容)。

可在控制器中注入的$transclude服务

在开发者指南中对$transclude服务是这么解释的:

$transclude - A transclude linking function pre-bound to the correct transclusion scope: function(cloneLinkingFn).

看看如何用在我们的例子中:

在fiddle中查看例子:

<div ng-controller="parentController"> <button-bar> <button ng-click="onPrimary1Click()">{{primary1Label}}</button> <button>Primary2</button> <button>Secondary1</button> </button-bar> </div>

JS:

var testapp = angular.module('testapp', []); testapp.controller('parentController', ['$scope', '$window', function($scope, $window) { $scope.onPrimary1Click = function() { alert('Primary1 clicked'); }; $scope.primary1Label = "Prime1" }]); testapp.directive('primary', function() { return { restrict: 'C', link: function(scope, element, attrs) { element.addClass('btn btn-primary'); } } }); testapp.directive('secondary', function() { return { restrict: 'C', link: function(scope, element, attrs) { element.addClass('btn'); } } }); testapp.directive('buttonBar', function() { return { restrict: 'EA', template: '<div><div></div><div></div></div>', replace: true, transclude: true, scope: {}, controller: ['$scope', '$element', '$transclude', function ($scope, $element, $transclude) { $transclude(function(clone) { var primaryBlock = $element.find('div.primary-block'); var secondaryBlock = $element.find('div.secondary-block'); var transcludedButtons = clone.filter(':button'); angular.forEach(transcludedButtons, function(e) { if (angular.element(e).hasClass('primary')) { primaryBlock.append(e); } else if (angular.element(e).hasClass('secondary')) { secondaryBlock.append(e); } }); }); }], }; });

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzgzgz.html