angularJs關(guān)于指令的一些冷門屬性詳解
我們使用ng的時(shí)候,經(jīng)常會(huì)使用到指令,大家所熟知的屬性我在這里就不介紹了,講講大家沒怎么留意的屬性
1.multiElement
這是指定指令作用區(qū)間的功能,最常用的就是ng-repeat-start和ng-repeat-end了。
2.priority
指令優(yōu)先級(jí),優(yōu)先級(jí)越高,指令越早執(zhí)行。
3.terminal
是否允許優(yōu)先級(jí)低的指令起作用,如果是true,那么只有比當(dāng)前指令或跟當(dāng)前指令等級(jí)相同的指令才可以執(zhí)行。最典型的就是ngIf
4.templateNamespace
聲明模板的格式有三種選擇 svg、html、math
5.transclude
或許有人疑問了,transclude也算是冷門屬性嗎?其實(shí)大家對(duì)transclude了解并沒有想象的那么深,transclude是一個(gè)挺復(fù)雜的屬性,一般大家會(huì)用到的也僅僅是true,false。這兩個(gè)屬性我在這里就不講了,在這里我主要講的是transclude:element,我google了一整天都沒找到正確描述這個(gè)屬性的方法。我覺得google出來(lái)的答案太文檔化了。最后在研究$transclude才看出來(lái)這個(gè)屬性的功能究竟在哪里。再講功能前我們先了解下$transclude
無(wú)論在指令的compile還是link時(shí)期我們的最后一個(gè)參數(shù)就是$transclude了,這里其實(shí)我們看看源碼是如何定義的,我看的源碼是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); } }
還有一個(gè)另一個(gè)函數(shù)要特別指出來(lái),就是最后返回的 boundTranscludeFn 這個(gè)方法,下面是他的源碼
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 }); }
這兩個(gè)方法到底是在做什么呢?其實(shí)就是克隆了當(dāng)前指令的節(jié)點(diǎn),并生成子作用域??寺〉墓?jié)點(diǎn)由transclude定義,如果你的屬性是true,則克隆的是指令模板中的ng-transclude所在的DOM節(jié)點(diǎn),及其子節(jié)點(diǎn)。如果屬性是element則克隆整個(gè)模板的節(jié)點(diǎn)。
這是兩個(gè)指令的代碼
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干擾了對(duì)結(jié)果的理解,你可以注釋掉,然后查看控制臺(tái)中打印出來(lái)的clone,你就能知道所謂transclude的屬性聲明為element的作用了,我們打開replace目的在于能較清楚的查看DOM節(jié)點(diǎn),來(lái)獲得結(jié)論,下面就是兩者編譯后DOM節(jié)點(diǎn)的區(qū)別了
看完上面的圖,你可以明顯的區(qū)別到兩者對(duì)DOM的克隆不一樣的,另外如果在聲明屬性為‘element'時(shí),需要聲明replace為true,才能渲染出來(lái)。我查了很多資料,最終用斷點(diǎn)得出了我認(rèn)為對(duì)的結(jié)論,斷點(diǎn)追蹤的結(jié)果是發(fā)現(xiàn)如果不聲明replace,好像就不會(huì)執(zhí)行ngTransclude指令,這點(diǎn)我很奇怪,正因?yàn)檫@樣子所以導(dǎo)致沒有成功渲染。二歸根結(jié)底其實(shí)是兩者的操作的DOM元素不同,在聲明transclude為element時(shí),replace為true,你取到的DOM節(jié)點(diǎn)是含有transclude屬性的節(jié)點(diǎn)(子節(jié)點(diǎn)),而為false你拿到的并不是含有transclude屬性的節(jié)點(diǎn)(父節(jié)點(diǎn)),而ng本身不對(duì)其節(jié)點(diǎn)進(jìn)行遍歷,導(dǎo)致沒能執(zhí)行ngTransclude指令
我看到一個(gè)觀點(diǎn)覺得不錯(cuò),大概意思就是:源于功能的考慮,在使用element屬性的時(shí)候,一般都是起占位符的作用,你需要做的操作是對(duì)DOM的添加時(shí)候,才會(huì)用到這個(gè)克隆功能。
我覺得這個(gè)觀點(diǎn)不錯(cuò),看過很多關(guān)于ngrepeat的介紹,很多文章都說(shuō)ngrepeat源碼是通過$scope.$new()來(lái)生成子作用域的,實(shí)際上并不完全正確,他的確是通過$scope.$new產(chǎn)生子作用域的,但是這個(gè)產(chǎn)生功能是交給$transclude函數(shù)去做得,實(shí)際上ngrepeat的源碼上是通過$transclude來(lái)生成子作用域和添加DOM節(jié)點(diǎn)的。與上面的觀點(diǎn)有相似之處。
以上就是小編為大家?guī)?lái)的angularJs關(guān)于指令的一些冷門屬性詳解全部?jī)?nèi)容了,希望大家多多支持腳本之家~
相關(guān)文章
Angular搜索 過濾 批量刪除 添加 表單驗(yàn)證功能集錦(實(shí)例代碼)
這篇文章主要介紹了Angular搜索 過濾 批量刪除 添加 表單驗(yàn)證功能集錦(實(shí)例代碼),需要的朋友可以參考下2017-10-10Angularjs中的事件廣播 —全面解析$broadcast,$emit,$on
下面小編就為大家?guī)?lái)一篇Angularjs中的事件廣播 —全面解析$broadcast,$emit,$on。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考,一起跟隨小編過來(lái)看看吧2016-05-05Angular2表單自定義驗(yàn)證器的實(shí)現(xiàn)
本文給大家介紹angular2表單自定義驗(yàn)證器的實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧2016-10-10angular 組件通信的幾種實(shí)現(xiàn)方式
這篇文章主要介紹了angular 組件通信的幾種實(shí)現(xiàn)方式,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2018-07-07Angular.Js之Scope作用域的學(xué)習(xí)教程
這篇文章主要給大家分享了關(guān)于Angular.Js之Scope作用域的學(xué)習(xí)教程 ,文中通過多個(gè)示例代碼介紹的非常詳細(xì),相信對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-04-04Angular應(yīng)用tsconfig.json中的lib屬性示例解析
這篇文章主要介紹了Angular應(yīng)用tsconfig.json中的lib屬性示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07