日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

angularJs关于指令的一些冷门属性

發布時間:2023/12/18 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 angularJs关于指令的一些冷门属性 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  我們使用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節點的。與上面的觀點有相似之處。

  就講到這里了,這是作者原創,轉載請注明

轉載于:https://www.cnblogs.com/HeJason/p/5514690.html

總結

以上是生活随笔為你收集整理的angularJs关于指令的一些冷门属性的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。