原文
https://www.jianshu.com/p/9d7249922bda
大綱
1、angular的DOM操作
2、為什么不能直接操作DOM?
3、三種錯誤操作DOM的方式
4、angular2如何DOM操作的機制?
5、正確操作DOM的方式
6、為什么需要ElementRef
7、使用ElementRef的代碼實例及優化
8、代碼資源
angular的DOM操作
angular2的設計目標本來就是要讓瀏覽器和DOM獨立。DOM是復雜的,因此使組件與它分離,會讓我們的應用程序,更容易測試和重構。為了支持跨平台,Angular還通過抽象封裝了不同平台的差異。
為什么不能直接操作DOM?
angular2采用AOT靜態編譯模式,這種形式下需要我們的模板類型必須是穩定和安全的,直接使用javascript和jquery語言是不穩定,因為他們的編譯不會提前發現錯誤,所以angular2才會選擇javascript的超集typescript語言(這種語言編譯期間就能發現錯誤)。
三種錯誤操作DOM的方式
@Component({ ... }) export class HeroComponent { constructor(private _elementRef: ElementRef) {} doBadThings() { $('id').click(); //jquery this._elementRef.nativeElement.xyz = ''; //原生的ElementRef document.getElementById('id'); //javascript } }
angular2如何DOM操作的機制?
為了能夠支持跨平台,Angular 通過抽象層封裝了不同平台的差異。比如定義了抽象類 Renderer、Renderer2 、抽象類 RootRenderer 等。此外還定義了以下引用類型:ElementRef、TemplateRef、ViewRef 、ComponentRef 和 ViewContainerRef 等。
正確操作DOM的方式
angular通過ElementRef實現跨平台,用Renderer實現視圖應用相分離,想必也是一種很贊的設計模式。
為什么需要ElementRef
angular一直在做的一件事情就是降低視圖層和應用層之間的耦合,在應用層直接操作DOM,會導致應用層和視圖層之間強耦合,導致我們不能將應用運行在不同的環境中。比如令js能夠實現多線程的webWorker,在webWorker中,卻不能直接操作DOM,angular為我們封裝了一個對象,叫做ElementRef,能夠獲取到視圖層中的native對象,比如在瀏覽器中,native對象就是DOM對象。
export class ElementRef { public nativeElement: any; constructor(nativeElement: any) { this.nativeElement = nativeElement; } }
使用ElementRef的代碼實例及優化
1、簡單使用實例
通過this.elementRef.nativeElement.querySelector()獲取元素節點,然后對元素及節點設置樣式。
2、優化1
在ngAfterViewInit生命周期鈎子中對DOM元素進行樣式的初始化設置
3、優化2
利用ViewChild來獲取Child DOM對象的引用。
4、優化3
angular為我們提供了一個叫做Renderer的對象,它作為視圖層和應用層的粘合劑,能夠使我們把視圖層和應用層做到最大程度的分離。
通過注入Renderer,我們可以輕松的操作DOM,並且對視圖層和應用的分離做到最大限度。
代碼資源
在這里我就不粘貼源碼了,這樣整篇的篇幅會很大,這里我就將大概的原理粘貼出來。如果對Dom操作的代碼有興趣的讀者可以從我的git上查看。angular實例代碼中的angular-dom項目里就是該篇博客中提及的代碼實例。