亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

AngularJS中transclude用法詳解

2019-11-20 08:36:07
字體:
來源:轉載
供稿:網友

本文實例講述了AngularJS中transclude用法。分享給大家供大家參考,具體如下:

Transclude - 在Angular的指令中,大家會看到有一個這樣的一個配置屬性,這個單詞在英文字典里面也查詢不到真實的意思,所以就用英文來標示它吧。如果你深入的使用angular的話,你就花很大一部分時間來創建自定義指令,那么就不可避免的要深入理解transclude。簡單的講,transclude主要完成以下工作,取出自定義指令中的內容(就是寫在指令里面的子元素),以正確的作用域解析它,然后再放回指令模板中標記的位置(通常是ng-transclude標記的地方),雖然使用內建的ngTransclude對于基本的transclude操作已經足夠簡單,但是在文檔中對這個transclude的解釋還是有存在很多疑惑,比如說:

在compile函數中接收到了一個叫transclude的參數是什么東西呢?有什么用呢?

在控制器中也有個叫$transclude的可以通過依賴注入的服務,這又是什么呢?

隔離作用域跟transclude有什么關系?

屬性的transclude操作

接下來我們將一個個的解釋:

基本的transclude

我們通過一個基本的transclude例子來講解吧,我們現在要創建的是一個叫buttonBar的指令,用戶可以通過它來添加一組button到頁面上,這個指令會對不同的button進行位置的排列。以下例子css樣式是使用Bootstrap框架。

在fiddle中查看例子:http://jsfiddle.net/ospatil/A969Z/157/

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

JS:

var testapp = angular.module('testapp', []);testapp.controller('parentController', ['$scope', '$window', function($scope, $window) {  console.log('parentController scope id = ', $scope.$id);  $scope.primary1Label = 'Prime1';  $scope.onPrimary1Click = function() {    $window.alert('Primary1 clicked');  };}]);testapp.directive('primary', function() {  return {    restrict: 'C',    link: function(scope, element, attrs) {      element.addClass('btn btn-primary');    }  }});testapp.directive('buttonBar', function() {  return {    restrict: 'EA',    template: '<div class="span4 well clearfix"><div class="pull-right" ng-transclude></div></div>',    replace: true,    transclude: true  };});

我們先看下HTML標簽,buttonBar指令包裹著幾個button元素。而button元素也被鏈接上了基于class的primary指令,不要太在意這個primary指令的功能它只不過為button元素添加一些css的樣式而已?,F在我們來看buttonBar指令,它提供了一個transclude:true屬性,同時在它的模板里面使用ng-transclude指令。在運行的過程中,Angular獲取到自定義指令的內容,處理完了之后把結果放到了模板中鏈接上ng-transclude的div。

transclude到多個位置

現在我們來增強下我們的buttonBar指令的功能,我們增加了兩種按鈕,primary和secondary,其中primary按鈕是排右邊,secondary是排左邊。所以要做到這個功能,它必須能夠取出指令的內容,然后把它們分別添加到不同的div中,一個用來放primary按鈕, 一個用來放secondary按鈕。

這樣的話,默認的機制已經滿足不了我們的要求,于是我們有了另外一種方法:

設置transclude為true

手工移動button元素到合適的div

最后,在指令的編譯或鏈接函數中移除原始的用來transclude操作的元素

這種方法就是先把所有的內容插入到ng-transclude標記的元素中,然后在link函數中再找出元素的插入的元素,重新放到元素的其他地方,最后刪除原來暫存內容的元素。

在fiddle中查看例子:http://jsfiddle.net/ospatil/A969Z/158/

<div ng-controller="parentController">  <button-bar>    <button class="primary" ng-click="onPrimary1Click()">{{primary1Label}}</button>    <button class="primary">Primary2</button>    <button class="secondary">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 class="span4 well clearfix"><div class="primary-block pull-right"></div><div class="secondary-block"></div><div class="transcluded" ng-transclude></div></div>',    replace: true,    transclude: true,    link: function(scope, element, attrs) {      var primaryBlock = element.find('div.primary-block');      var secondaryBlock = element.find('div.secondary-block');      var transcludedBlock = element.find('div.transcluded');      var transcludedButtons = transcludedBlock.children().filter(':button');      angular.forEach(transcludedButtons, function(elem) {        if (angular.element(elem).hasClass('primary')) {          primaryBlock.append(elem);        } else if (angular.element(elem).hasClass('secondary')) {          secondaryBlock.append(elem);        }      });      transcludedBlock.remove();    }  };});

雖然這種方法達到了我們的目的,但是允許默認的transclude操作,然后再人工的從DOM元素中移出不是非常有效率的。因此,我們有了compile函數中的transclude參數和控制器中的$transclude服務

編譯函數參數中的transclude

開發者指南中給了我們以下的關于指令中編譯函數的形式:

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

其中關于第三個參數transclude的解釋是:

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

好的,現在我們利用這個函數來實現我們剛才講到的功能,從而不需要再先暫存內容,然后再插入到其他地方。

在fiddle中查看例子:http://jsfiddle.net/ospatil/A969Z/161/

<div ng-controller="parentController">  <button-bar>    <button class="primary" ng-click="onPrimary1Click()">{{primary1Label}}</button>    <button class="primary">Primary2</button>    <button class="secondary">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 class="span4 well clearfix"><div class="primary-block pull-right"></div><div class="secondary-block"></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中查看例子:http://jsfiddle.net/ospatil/A969Z/162/

<div ng-controller="parentController">  <button-bar>    <button class="primary" ng-click="onPrimary1Click()">{{primary1Label}}</button>    <button class="primary">Primary2</button>    <button class="secondary">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 class="span4 well clearfix"><div class="primary-block pull-right"></div><div class="secondary-block"></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);          }        });      });    }],  };});

同樣的意思,$transclude中接收的函數里的參數含有指令元素的內容,而$element包含編譯后的DOM元素,所以就可以在控制器中同時操作DOM元素和指令內容,跟上文的compile函數的實現方式有異曲同工之處,這里有幾點需要注意,這個控制器應該是指令的控制器,另一個注意到上文除了第一種方法,其他的地方都沒有用到ng-transclude,因為無需插入到模板中。

Transclude 和 scope

在開發者指南中提到了a directive isolated scope and transclude scope are siblings,這到底是什么意思呢?假如你認真看前文的例子的話,你就會發現parentController控制器創建了一個作用域,buttonBar指令在parentController下面創建了一個孤立作用域,而根據Angular文檔,transclude也創建了另外一個作用域,因此指令的隔離作用域跟transclude作用域是基于同一個父作用域的兄弟作用域。

transclude內容放入元素的屬性

實際上,你不可以這么做,但是你可以通過一種變通的方法來實現這種效果

var testapp = angular.module('testapp', [])testapp.directive('tag', function() { return {  restrict: 'E',  template: '<h1><a href="{{transcluded_content}}">{{transcluded_content}}</a></h1>',  replace: true,  transclude: true,  compile: function compile(tElement, tAttrs, transclude) {    return {      pre: function(scope) {        transclude(scope, function(clone) {         scope.transcluded_content = clone[0].textContent;        });      }    }  } }});

這里沒有操作DOM元素,只是把元素的文本內容復制給了作用域屬性,然后在通過作用域傳給屬性。

另外要注意的是,這里的clone參數是jquery或angular.element封裝的整個模板元素。

// todoadd comparing with ng-include

希望本文所述對大家AngularJS程序設計有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲va欧美va国产综合久久| 国产精品一区二区电影| 成人有码视频在线播放| 国产激情久久久久| 热99精品只有里视频精品| 久久成人免费视频| 久久99久久99精品免观看粉嫩| 中文字幕最新精品| 91久久久国产精品| 日韩暖暖在线视频| 欧美中文字幕视频在线观看| 91在线免费观看网站| 欧美色欧美亚洲高清在线视频| 精品国内亚洲在观看18黄| 色综合久久天天综线观看| 欧美大片va欧美在线播放| 久久精品视频播放| 欧美精品在线看| 久久全球大尺度高清视频| 国产亚洲欧洲黄色| 92国产精品视频| 久久99亚洲热视| 日韩人在线观看| 精品久久久av| 亚洲成人激情小说| 日韩精品在线观看一区| 久久亚洲国产成人| 麻豆国产va免费精品高清在线| 2020欧美日韩在线视频| 久久精品国产欧美亚洲人人爽| 97欧美精品一区二区三区| 国产精品白丝jk喷水视频一区| 亚洲精品美女久久久| 久久久久久久国产精品| 日韩中文字幕国产| 日韩视频免费看| 久久99视频精品| 日韩欧美国产黄色| 精品国产欧美一区二区五十路| 亚洲福利视频网站| 国产精品av电影| 亚洲人精品午夜在线观看| 奇米成人av国产一区二区三区| 亚洲女人天堂网| 亚洲精品美女在线| 日韩欧美国产骚| 成人xxxx视频| 欧美第一淫aaasss性| 亚洲偷熟乱区亚洲香蕉av| 欧美成人免费观看| 国产成人高潮免费观看精品| 92国产精品视频| 69久久夜色精品国产69乱青草| 久久精品中文字幕免费mv| 大胆人体色综合| 国产视频999| 亚洲无线码在线一区观看| 色系列之999| 日韩欧美成人免费视频| 日韩精品中文字幕有码专区| 日本免费在线精品| 日韩精品一区二区视频| 欧美色视频日本版| 欧美巨乳在线观看| 久久精品人人做人人爽| 欧美人在线观看| 伊人男人综合视频网| 国产精品偷伦一区二区| 欧美限制级电影在线观看| 中文在线资源观看视频网站免费不卡| 色先锋资源久久综合5566| 日韩欧美在线字幕| 久久亚洲国产成人| 国产精品美女免费| 热re91久久精品国99热蜜臀| 7777精品久久久久久| 91亚洲精品一区| 中日韩美女免费视频网站在线观看| 中文一区二区视频| 欧美一级视频免费在线观看| 欧美成人四级hd版| 亚洲男人av在线| 综合激情国产一区| 一区二区亚洲欧洲国产日韩| 日韩第一页在线| 国产亚洲精品久久久久久牛牛| 国产一区二区三区高清在线观看| 国产精品99久久久久久久久| 韩国一区二区电影| 久久精品一偷一偷国产| 亚洲三级av在线| 精品亚洲男同gayvideo网站| 欧美高清无遮挡| 亚洲天堂免费视频| 久久精品亚洲热| 久热精品视频在线| 丝袜亚洲另类欧美重口| 国产精品久久久999| 亚洲欧美在线看| 成人黄色激情网| 国产成人av网| 伦理中文字幕亚洲| 亚洲最大激情中文字幕| 欧美一级淫片videoshd| 亚洲跨种族黑人xxx| 97精品视频在线| 国产精品免费视频久久久| 国产精品国产三级国产aⅴ9色| 亚洲免费小视频| 国产一区二区丝袜| 久久香蕉频线观| 色多多国产成人永久免费网站| 亚洲欧美在线一区| 久久全球大尺度高清视频| 亚洲深夜福利视频| 久久夜色精品国产亚洲aⅴ| 日日骚av一区| 久久综合五月天| 亚洲春色另类小说| 国产精品露脸自拍| 欧美巨猛xxxx猛交黑人97人| 日韩电影免费观看在线观看| 久久夜精品香蕉| 国产成人精品久久二区二区| 97在线日本国产| 北条麻妃一区二区在线观看| 黑人与娇小精品av专区| 国产成人激情小视频| 欧美在线一级va免费观看| 欧美激情videos| 久热精品视频在线观看一区| 成人亚洲综合色就1024| 国产精品亚洲аv天堂网| 高清欧美一区二区三区| 亚洲精品suv精品一区二区| 一区二区三区美女xx视频| 搡老女人一区二区三区视频tv| 最新亚洲国产精品| 精品国产乱码久久久久久虫虫漫画| 姬川优奈aav一区二区| 久久精品99国产精品酒店日本| 日韩精品中文字幕在线观看| 国产女人18毛片水18精品| 亚洲欧美在线免费| 国产啪精品视频网站| 欧美精品九九久久| 国产欧美日韩亚洲精品| 成人网在线免费看| 亚洲黄页网在线观看| 亚洲国产小视频| 亚洲永久在线观看| 久久国内精品一国内精品| 精品人伦一区二区三区蜜桃免费| 成人免费看吃奶视频网站| 91精品国产高清久久久久久| 国外成人性视频| 成人www视频在线观看| 日韩国产高清污视频在线观看| 欧美在线播放视频| 日韩最新中文字幕电影免费看| 亚洲欧美在线一区| 精品偷拍一区二区三区在线看| 国产盗摄xxxx视频xxx69| 上原亚衣av一区二区三区|