Angular2學(xué)習(xí)筆記-組件中的DOM操作

有時(shí)不得不面對一些需要在組件中直接操作DOM的情況,如我們的組件中存在大量的CheckBox,我們想獲取到被選中的CheckBox缅疟,然而這些CheckBox是通過循環(huán)產(chǎn)生的,我們無法給每一個CheckBox指定一個ID哲戚,這個時(shí)候可以通過操作DOM來實(shí)現(xiàn)。angular API中包含有viewChild艾岂,contentChild等修飾符顺少,這些修飾符可以返回模板中的DOM元素。

指令中的DOM操作

@Directive({
selector: 'p'
})
export class TodoDirective{
constructor(el: ElementRef, renderer: Renderer){
renderer.setElementStyle(el.nativeElement, 'backgroundColor', 'red');
}
}
以上聲明了一個指令王浴,使用是需要在module中的declarations中聲明脆炎。該指令的作用是將p元素的backgroundColor設(shè)置為red。
-ElementRef是一個允許直接獲取DOM元素的一個類氓辣,該類包含一個nativeElement屬性秒裕。當(dāng)不允許直接操作原生DOM元素時(shí),該屬性值為null筛婉。
-Renderer該類包含大量可以用來操作DOM原生的方法簇爆。

@ViewChild和@ViewChildren

每一個組件都有一個視圖模板,通過 template或templateUrl引入爽撒。想要獲取視圖模板中的DOM元素則可以使用@ViewChild和@ViewChildren修飾符。他們可以接受模板變量或元素標(biāo)簽或模板類名來獲取DOM節(jié)點(diǎn)响蓉。@ViewChild返回ElementRef類引用(獲取組件時(shí)則直接使用組件類名)硕勿,而@ViewChildren返回QueryList<ElementRef>。

//模板內(nèi)容
<p *ngFor='let item of todos' #name>{{ item.name }}</p>

//組件中獲取DOM
@ViewChildren('name')
todoNames: QueryList<ElementRef>;

@ViewChild('name')
todoName: ElementRef;
ngAfterViewInit(){
this.todoNames.forEach(e=>console.log(e.nativeElement.innerText));
console.log(this.todoName.nativeElement.innerText);
}
@ViewChild('name')和@ViewChildren('name')通過name模板變量獲取p標(biāo)簽DOM節(jié)點(diǎn)枫甲,可以在ngAfterViewInit聲明周期鉤子中獲取節(jié)點(diǎn)信息源武,當(dāng)然也可以在其他函數(shù)中扼褪,只要保證視圖完成初始化即可。
QueryList是一個不可變的列表粱栖,其存在一個名為changes的Observable變量话浇,因此可以被訂閱,結(jié)合notifyOnChanges方法闹究,可以實(shí)時(shí)查看QueryList中變量的變化幔崖。調(diào)用notifyOnChanges函數(shù)后,當(dāng)組件的輸入發(fā)生變化時(shí)會觸發(fā)Observable發(fā)出新的值渣淤,這樣當(dāng)todoNames: QueryList<ElementRef>有更新時(shí)赏寇,便能通過下面代碼查看到變化:

this.todoNames.changes.subscribe(data => data._results.forEach(
e=>console.log(e.nativeElement.innerText)));
this.todoNames.notifyOnChanges();
@ContentChild和@ContentChildren

看著與@ViewChild和@ViewChildren很相似,但@ContentChild和@ContentChildren是獲取組件標(biāo)簽中的內(nèi)容的价认,懶得寫例子嗅定,這里直接貼上angular中文官網(wǎng)的一個例子:

import {Component, ContentChildren, Directive, Input, QueryList} from '@angular/core';
@Directive({selector: 'pane'})
export class Pane {
@Input() id: string;
}
@Component({
selector: 'tab',
template: <div>panes: {{serializedPanes}}</div>
})
export class Tab {
@ContentChildren(Pane) panes: QueryList<Pane>;
get serializedPanes(): string { return this.panes ? this.panes.map(p => p.id).join(', ') : ''; }
}
@Component({
selector: 'example-app',
template: <tab> <pane id="1"></pane> <pane id="2"></pane> <pane id="3" *ngIf="shouldShow"></pane> </tab> <button (click)="show()">Show 3</button>,
})
export class ContentChildrenComp {
shouldShow = false;
show() { this.shouldShow = true; }
}
可以看出@ContentChildren(Pane) panes: QueryList<Pane>;獲取的是組件Tab中的內(nèi)容:

<tab>
<pane id="1"></pane>
<pane id="2"></pane>
<pane id="3" *ngIf="shouldShow"></pane>
</tab>
與@ViewChild類似@ContentChild獲取的是第一個Pane指令,獲取DOM元素后用踩,可以采用類似的方式處理渠退。

TemplateRef

模板的概念應(yīng)該是大多數(shù)Web開發(fā)人員熟悉的。在整個應(yīng)用程序的視圖中重復(fù)使用一組DOM元素脐彩。在HTML5標(biāo)準(zhǔn)引入了template標(biāo)簽之前碎乃,大多數(shù)都是用下面這種方式實(shí)現(xiàn),增加type屬性:

<script>
let tpl = document.querySelector('#tpl');
let container = document.querySelector('.insert-after-me');
insertAfter(container, tpl.content);
</script>
<div class="insert-after-me"></div>
<ng-template id="tpl">
<span>I am span in template</span>
</ng-template>
Angular支持這種方法丁屎,并實(shí)現(xiàn)TemplateRef類來處理模板荠锭。以下是如何使用它:

@Component({
selector: 'sample',
template: <ng-template #tpl> <span>I am span in template</span> </ng-template>
})
export class SampleComponent implements AfterViewInit {
@ViewChild("tpl") tpl: TemplateRef<any>;

ngAfterViewInit() {
    let elementRef = this.tpl.elementRef;
    // outputs `template bindings={}`
    console.log(elementRef.nativeElement.textContent);
}

}
Angular從DOM中刪除模板元素,并在其位置插入注釋晨川。這是呈現(xiàn)時(shí)的樣子:

<sample>

</sample>
TemplateRef類本身就是一個簡單的類证九。It holds a reference to its host element in elementRef property and has one method createEmbeddedView。這個方法是非常有用的共虑,因?yàn)樗试S我們創(chuàng)建一個視圖并以ViewRef的形式返回一個引用

ViewRef

Angular鼓勵開發(fā)人員將UI視為Views的組合愧怜,而不是將其視為獨(dú)立的HTML標(biāo)記樹。

Angular支持2種視圖

Embedded Views which are linked to a Template
Host Views which are linked to a Component
Creating embedded view

ngAfterViewInit() {
let view = this.tpl.createEmbeddedView(null);
}
Creating host view

constructor(private injector: Injector,
private r: ComponentFactoryResolver) {
let factory = this.r.resolveComponentFactory(ColorComponent);
let componentRef = factory.create(injector);
let view = componentRef.hostView;
}
ViewContainerRef

表示可以附加一個或多個視圖的容器妈拌。

首先要提到的是拥坛,任何DOM元素都可以用作視圖容器。通常尘分,ViewContainer與ng-container結(jié)合使用猜惋。ng-container會被渲染為一個注釋,所以它不會在DOM中引入多余的html元素培愁。以下是在組件模板的特定位置創(chuàng)建ViewContainer的示例:

@Component({
selector: 'sample',
template: <span>I am first span</span> <ng-container #vc></ng-container> <span>I am last span</span>
})
export class SampleComponent implements AfterViewInit {
@ViewChild("vc", {read: ViewContainerRef}) vc: ViewContainerRef;

ngAfterViewInit(): void {
    // outputs `template bindings={}`
    console.log(this.vc.element.nativeElement.textContent);
}

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末著摔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子定续,更是在濱河造成了極大的恐慌谍咆,老刑警劉巖禾锤,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異摹察,居然都是意外死亡恩掷,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門供嚎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來黄娘,“玉大人,你說我怎么就攤上這事查坪〈绾辏” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵偿曙,是天一觀的道長氮凝。 經(jīng)常有香客問我,道長望忆,這世上最難降的妖魔是什么罩阵? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮启摄,結(jié)果婚禮上稿壁,老公的妹妹穿的比我還像新娘。我一直安慰自己歉备,他們只是感情好傅是,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蕾羊,像睡著了一般喧笔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上龟再,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天书闸,我揣著相機(jī)與錄音,去河邊找鬼利凑。 笑死浆劲,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的哀澈。 我是一名探鬼主播牌借,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼割按!你這毒婦竟也來了走哺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤哲虾,失蹤者是張志新(化名)和其女友劉穎丙躏,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體束凑,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晒旅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了汪诉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片废恋。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖扒寄,靈堂內(nèi)的尸體忽然破棺而出鱼鼓,到底是詐尸還是另有隱情,我是刑警寧澤该编,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布迄本,位于F島的核電站,受9級特大地震影響课竣,放射性物質(zhì)發(fā)生泄漏嘉赎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一于樟、第九天 我趴在偏房一處隱蔽的房頂上張望公条。 院中可真熱鬧,春花似錦迂曲、人聲如沸靶橱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽关霸。三九已至,卻和暖如春鬓长,著一層夾襖步出監(jiān)牢的瞬間谒拴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工涉波, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留英上,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓啤覆,卻偏偏與公主長得像苍日,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子窗声,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容