angular6 render2 & viewContentRef實踐


angular 渲染層

 

angular一個跨平台的框架不僅僅針對的瀏覽器這一個平台

ElementRef 與 TemplateRef

  簡單的理解:

               ElemnetRef : 例如一個<span>元素的引用;

               TemplateRef: 例如template模板的引用;

再angular中,官方的說法是: 不推薦使用ElementRef來改變元素的樣式屬性值或者操作DOM元素,原因是,angular是一個跨平台的框架,如果直接使用ElementRef對DOM直接進行操作,那么在其他平台情況下會出事。那么真的的正規操作DOM是使用什么呢? 官方推薦: 僅使用render2來改變DOM元素的樣式,僅使用viewContentRef來改變DOM的結構,不推薦使用render2來改變DOM結構,為什么呢?

 不推薦使用Render2來改變DOM結構的原因

 首先了解一下angular中如何將組件轉為視圖

 

 view 與 HTML 元素的關系

 

使用render2操作DOM結構,只是將DOM的標簽移除,但是在視圖中的標簽view並沒有被真的移除,這就是為什么改變DOM結構不推薦使用render2的原因

實戰

1. 使用TemplateRef關聯元素 結合render2改變元素的樣式

首先了解一下render2幾個常用API

box.component.html

<div>div 1</div>
<div #targetDiv>targerDiv</div>

box.component.ts

export class BoxComponent implements OnInit, AfterViewInit {
    @ViewChild('targetDiv') targetDiv: ElementRef; constructor(private _elementRef: ElementRef, private _render: Renderer2) { } ngOnInit() { } ngAfterViewInit(): void { this._render.setStyle(this.targetDiv.nativeElement, 'background', 'pink'); console.log(this._elementRef.nativeElement); console.log(this.targetDiv); } }

效果圖

2. 使用ViewContentRef創建元素

總體思路:viewContentRef引用<ng-container>標簽,<ng-container>是angular里的一種映射,在沒有真的內容出現的時候,<ng-container>只是一個隱式的占位符,最后動態生成的元素會被填充到這個占位符中,由viewContentRef的實例使用自帶的API來創建元素,元素應該是一開始就寫好的,但是其DOM結果沒有被渲染出來,在angular中<ng-template>中的內容會被忽略,我們需要做的是創建<ng-tempate>的引用,然后給到viewContentRef的實例<ng-tempate>中的元素自然會被顯示出來。

    首先了解一下ViewContentRef的常用API

  

ViewContentRefComponent.html
<!--<ng-template><span #span>i am span to removed</span></ng-template>-->
<ng-template><a>i am a to removed</a></ng-template>
<ng-container #vc></ng-container>
<button (click)="remove()">remove</button>
<button (click)="create()">create</button>
ViewContentRefComponent.ts
export class ViewContentRefComponent implements OnInit, AfterViewInit {
    // @ViewChildren('span') spanElemnet;
    // @ViewChildren('a') aElement;
 @ViewChild(TemplateRef) template; @ViewChild('vc', {read: ViewContainerRef}) vc; constructor() { } ngOnInit() { // console.log(this.spanElemnet); console.log(this.template); console.log(this.vc); } ngAfterViewInit(): void { this.vc.createEmbeddedView(this.template); // console.log(this.spanElemnet.length);  } remove = () => { this.vc.remove(); } create = () => { this.vc.createEmbeddedView(this.template); } }

2.  使用viewContentRef創建組件

總體思路:  創建一個組件;然后再要創建組件的另外一個組建中引用ViewContainerRef,將工廠解析器解析之后的組件(被創建的組件)ViewContainerRef的創建組件函數中即可

alerComponent.html

<p>name: {{name}}</p>
<p>age: {{age}}</p>

alerComponent.ts

export class AlertComponent implements OnInit {
    @Input() name = ''; @Input() age = 0; constructor() { } ngOnInit() { } }

createAlert.html

<ng-template #contatiner></ng-template>
<button (click)="create()">create alter component</button>
<button (click)="remove()">remove component</button>

createAlert.componts.ts

export class CreateAlertComponent implements OnInit {
    @ViewChild('contatiner', {read: ViewContainerRef}) contatiner; alertComponent: ComponentRef<any>; constructor(private componentFactoryResolver: ComponentFactoryResolver) { } ngOnInit() { } create = (): void => { this.contatiner.clear(); this.alertComponent = this.contatiner.createComponent(this.componentFactoryResolver.resolveComponentFactory(AlertComponent)); this.alertComponent.instance.name = 'lili'; this.alertComponent.instance.age = 12; } remove = (): void => { // 被創建的組件進行自我銷毀 this.alertComponent.destroy(); } }

最終效果,可以拉取代碼跑一下。

 

         

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM