您好,登錄后才能下訂單哦!
前言
AngularJS中指令的重要性是不言而喻的,指令讓我們可以創(chuàng)建自己的HTML標記,它將自定義元素變成了一個一個的模塊,極大的體現(xiàn)了前端開發(fā)中的模塊化模式,并提高了代碼的易讀性和重用性。AngularJS中的指令也是學習AngularJS中的一個難點所在,其中的許多屬性,需要反復學習,認真體會,方能領(lǐng)悟其中的精妙之處。
今天我們要講的就是其中一個重點和難點 – transclusion。關(guān)于這個話題我之前也寫過很多文章來講述,但是當時都是照搬博文中的例子,自己也沒有比較深刻的體會,因此一直不得要領(lǐng)。今天我們的目標就是“徹底弄懂transclusion”。
一、什么是transclusion
好吧,我知道你肯定會去查詞典,但是你會發(fā)現(xiàn),詞典上沒有transclusion這個詞的準確釋義?。?!納尼?。?!這不坑爹的嗎!?。。?/p>
還好,維基百科上有一個注釋,翻譯過來意思大概是這樣的:
transclusion在計算機科學中指的是講一個文檔或者一個文檔的某部分在另一個文檔中引用。
我去,這不坑爹的嗎?。?!什么意思!?。?!
確實,你猜對了,這個解釋對我們一點幫助都沒有?。。。。?!
還好,我們終于在某道詞典找到了一個解釋:“嵌入”,這里指的是transclusion這個詞,而在后面我們即將看到的transclude這個詞壓根在詞典上就找不到。算了,淡定一點,繼續(xù)往下看。其實這里翻譯為“嵌入”,如果從實際運用中來看,還是比較貼切的。如果你不太理解什么是transclusion,我們下面用一個例子來說明一下。
ok,現(xiàn)在我們要創(chuàng)建一個指令了,我們把這個指令叫做<handsome-me>
。在此先略過這個指令的創(chuàng)建過程,如果你還不知道怎樣創(chuàng)建一個指令,請前參看前面幾篇文章。
好了,無論怎么說,這個指令已經(jīng)創(chuàng)建好了,于是我們可以有以下幾種用法:
第一種:
<handsome-me/>
就像是input一樣對吧,很簡單,我們叫它“自開自閉”(要是你在別的書上沒看過這個名稱,那就是我發(fā)明的,反正就這么叫)標簽。
第二種:
<handsome-me></handsome-me>
就像是div一樣對吧,更簡單,我們叫它“自開別人閉”(同上同上)標簽。
第三種:
<handsome-me> //中間有好多代碼 </handsome-me>
這個和第二種很像吧,但是又有點區(qū)別,我們叫它“自開別人閉,中間加一坨”(總是感覺好粗俗。。。never mind。。。)標簽。
我們來對比以下三種標簽,它們有什么區(qū)別。當然區(qū)別很多。但是具體到我們今天的話題,與之相關(guān)的最大的區(qū)別就是前兩種中間沒有加一坨,第三種中間加了一坨。OK,因此我們現(xiàn)在來總結(jié)什么叫做transclusion:
如果你在定義指令的時候,想要它在具體使用時中間加一坨,那么你就要用transclusion。
這個定義實在是太經(jīng)典了,完全比什么官方文檔要清楚有沒有,完爆各種老外唧唧歪歪說半天還是不明白有沒有,完全符合中國國情有沒有?。。?/p>
好了,知道了定義以后,我們要開始來看看具體怎么使用transclusion了。如果你了解AngularJS指令的編寫,你一定知道return的那個對象的tranclude指令默認是false,因此如果你想要開啟使用transclusion的話,就要將這個transclude屬性賦上一個別的值,當然,這個值不能亂賦,它只有兩種選擇:
第一種選擇:
transclude: true
第二種選擇:
transclude: 'element'
我去,這個又是毛線??!兩者之間有毛的區(qū)別?。?!文檔完全是看不懂的嘛!?。?/p>
淡定一點,現(xiàn)在我們來說區(qū)別。最常用的呢,是第一種,也就是賦值為true。還記得transclusion的中文意思嗎,“嵌入”對吧!因此我們現(xiàn)在就不說“一坨”,而把中間的這一坨叫做“嵌入部分”。ok,回到正題,當transclude是true的時候,嵌入部分就是嵌入部分,比如說:
<handsome-me> {{name}} <handsome-me>
在transclude:true
的時候,它的嵌入部分是什么???對了,就是{{name}}
。再來一發(fā):
<handsome-me> <div> <span>{{name}}</span> </div> <handsome-me>
在transclude:true
的時候,它的嵌入部分是什么???對了,是
<div> <span>{{name}}</span> </div>
太簡單了是吧!so easy!媽媽再也不用擔心我的學習?。?!
現(xiàn)在再來講第二種情況,當transclude的值是element的時候,又是怎樣一種情形。此時,嵌入部分變成了原來的嵌入部分加上外邊的自定義標簽,也就是整個元素。又聽不懂了?。?!fork fork fork!!!!!!淡定,我們再來舉例子:
<handsome-me> {{name}} <handsome-me>
在transclude:'element'
的時候它的嵌入部分是什么啊?對了,是:
<handsome-me> {{name}} <handsome-me>
再來一發(fā):
<handsome-me> <div> <span>{{name}}</span> </div> <handsome-me>
在transclude:'element'
的時候它的嵌入部分是什么???對了,是:
<handsome-me> <div> <span>{{name}}</span> </div> <handsome-me>
都說的這么詳細了,不要再說你不會了哈?。?!
二、ng-transclude的作用是什么
在編寫指令時,我們都會有一個template或者templateUrl這樣的屬性是吧。在使用transclusion時,我們要把嵌入部分放到模板中,因此我們有兩種選擇,其中一種選擇就是使用ng-transclude。
ng-transclude是干什么用的,我們還是先來看定義,再來看例子:
ng-tranclude決定了在什么地方放置嵌入部分。
太好理解了!于是我們來看例子:
假設(shè)指令是這樣的:
<handsome-me> {{name}} </handsome-me>
而模板是這樣的:
<div> <p>MaMa does not need to worry about my study anymore! </p> <div ng-transclude></div> </div>
于是,在transclude:true
的情況下,最終呈現(xiàn)在頁面中的HTML會是什么樣子。對了,是這樣:
<div> <p>MaMa does not need to worry about my study anymore! </p> {{name}} </div>
另一種情況,在transclude:'element'
的情況下,最終呈現(xiàn)在頁面中的HTML會是什么樣子。對了,是這樣:
<div> <p>MaMa does not need to worry about my study anymore! </p> <handsome-me> {{name}} </handsome-me> </div>
例子這么清楚,總能明白了吧??!
三、不使用ng-transclude的情形
OK,現(xiàn)在我們來想一個問題,如果我想把我的嵌入部分多次放入我的模板中怎么辦?你可能會說,那就多放幾個ng-transclude唄!這當然是不行的,在AngularJS中你只在一個指令的模板中只能申明一個ng-tranclude。所以這種情況下我們就能使用模板了,因此我們要使用一個叫做tranclude()
的函數(shù)!!
納尼!這又是什么東西!??!如果你仔細去研究一下AngularJS的文檔的話,你一定會發(fā)現(xiàn)一個叫做$tranclude的service,它就是我們現(xiàn)在要將講的東西。那么這個函數(shù)怎么用?如果你看過一些關(guān)于ng-repeat,ng-swift源碼的解析,你一定會記得其中的一個叫做linker的東西。這個東西上是什么曾經(jīng)困擾過我好長時間,但是后來我發(fā)現(xiàn)這個linker()
其實就是transclude()
。
我們在link,compile以及controller中都能找到這個transclude函數(shù)的身影。在link函數(shù)中,transclude是link函數(shù)的第五個參數(shù);在compile函數(shù)中,transclude是compile函數(shù)的第三個參數(shù)。在這個兩個函數(shù)中,由于我們沒有使用依賴注入,因此只要順序?qū)α司蛯α耍S便命名為什么都可以。而在controller函數(shù)中,由于使用的是依賴注入,因此transclude是$transclude,只要名字寫對了就對了。在link,compile和controller函數(shù)中,transclude的用法一模一樣,因此在這我們只舉一個link函數(shù)的例子:
1.最簡單的用法:
link(scope,elem,attrs,ctrl,transclude){ var content = transclude(); elem.append(content); }
在這里,我們通過transclude()
返回了嵌入部分的具體內(nèi)容,然后append到了元素的elem的尾巴上,當然,你想要append多次也是可以的。
2.復雜一點的用法:
link(scope,elem,attrs,ctrl,transclude){ tranclude(scope,function(clone){ elem.append(clone); }) }
這里tranclude接受了兩個參數(shù),第一個是scope,代表作用域。第二個回調(diào)函數(shù)中帶有一個參數(shù)clone,其實它就是嵌入內(nèi)容,和transclude()
的返回值一模一樣。那么前面的第一個參數(shù)的scope有什么用呢?這就要說到transclude和作用域了!
4.transclude和scope
我們知道,在定義一個指令時,如果不顯式聲明scope,那么指令的作用域就是父作用域。如果聲明scope:true
或者scope:{}
,那么指令會生成一個自己的作用域,只不過一個原型繼承,一個獨立而已。如果你使用transclusion,那么無論什么情緒,都會生成一個新的作用域,這個作用域直接原型繼承于父作用域,它的地位和指令生成的作用域是一樣的,二者屬于并列的關(guān)系。
于是我們現(xiàn)在就能了解tranclude(scope,function(clone){})
中的scope是什么意思了,默認情況下,如果我們簡單使用translude()
,那么作用域默認的是transclude生成的自作用域。但是如果我們使用tranclude(scope,function(clone){})
,那么作用域顯然就是directive的作用域了。要是我們想使用父作用域怎么辦,很簡單:
tranclude(scope.$parent,function(clone){})
要是想要一個新的作用域怎么辦,也很簡單:
tranclude(scope.$parent.$new(),function(clone){})
你要是文作用域是什么東西,作用域是怎么繼承的,那不是今天我們要講的話題。
說了這么多,這么直白,想必你已經(jīng)對AngularJS的transclusion徹底的清楚明白了吧。要是不明白,再看幾遍,總會明白的!??!
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對各位Android開發(fā)者們能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。