在angular中會有基本的jquery-lite,也就是angular.element
,當在include angular之前,就先include jquery,此時angular的jquery-lite,就會被自動替換成jquery。
替換angular.element的source code如下:
1 | function bindJQuery() { |
另外一個需要注意的地方就是jqLitePatchJQueryRemove
,會將jquery原生的function
,多經過一層處理,處理完在呼叫jquery的function
。
jqLitePatchJQueryRemove的source如下:
1 | function jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments) { |
其中element.triggerHandler('$destroy')
會告知angular底下的transcludedScope
,這個element已經被摧毀了,所以會導致,$element.detach
的時候,transcludedScope
無法被更新。element.triggerHandler('$destroy')
的監聽event可以參考createBoundTranscludeFn
這個function,會有下這段code去監聽:
1 | clone.on('$destroy', bind(transcludedScope, transcludedScope.$destroy)); |
在jqLitePatchJQueryRemove
只替換remove
、empty
、html
,而沒有替換detach
,使用detach
卻會影響scope
,真正原因要找jquery的source code。
因為detach間接呼叫了remove:
1 | detach: function( selector ) { |
Example(1.2.7):
- directive在ready中呼叫$element.detach:此時
transclude
裡面的scope將會失效。 - directive在ready之前呼叫$element.detach:
transclude
尚未被建立,自然而然就不會處理$destroy
的event,transclude
裡的scope仍然會work。
由此可知,只要scope尚未ready時,呼叫detach
就不會中斷scope的更新。若要讓directive
的scope正常運作,可用以下方式:
- 不使用transclude
- 不在scope ready中,使用detach
- 使用原生api
- 最後一種方式,jquery在angular之後include
如果不是這麼需要使用到jquery,建議就不要include了,當然jquery也提供很多方便的功能,依照project需求自己評估吧!