angularJs關於指令的一些冷門屬性詳解_AngularJS

來源:互聯網
上載者:User

我們使用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節點的區別了

看完上面的圖,你可以明顯的區別到兩者對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關於指令的一些冷門屬性詳解全部內容了,希望大家多多支援雲棲社區~

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.