angula中使用iframe點(diǎn)擊后不執(zhí)行變更檢測(cè)的問題
這個(gè)問題是上周的,當(dāng)時(shí)覺得這個(gè)問題的解決辦法太簡單了,不用寫博客記錄,但是潘老師今天今天又遇到了需要使用這個(gè)的地方,感覺問題雖然不難,但是,寫篇博客,方便自己查詢,也給了其他人搜索到解決辦法的機(jī)會(huì)。
問題描述
項(xiàng)目中使用到了ifame,理想狀態(tài)是:當(dāng)點(diǎn)擊ifame中的按鈕時(shí),將會(huì)調(diào)用通過angular寫的一個(gè)函數(shù),函數(shù)將會(huì)修改一個(gè)ngif的判斷條件,顯示一個(gè)彈窗,
但現(xiàn)實(shí)是:當(dāng)點(diǎn)擊ifame中的按鈕時(shí),將會(huì)調(diào)用通過angular寫的一個(gè)函數(shù),函數(shù)將會(huì)修改一個(gè)ngif的判斷條件,然后就沒有然后了.
開始的時(shí)候自己直接懵了, 方法確實(shí)執(zhí)行了, 但界面沒修改, 問了問潘老師, 潘老師說看看生命周期函數(shù)是否執(zhí)行了, 果然, 所有的生命周期函數(shù)都沒有調(diào)用。
解決辦法
既然生命周期函數(shù)沒調(diào)用,我們讓他調(diào)用不就行了,值已經(jīng)變化了,但是界面不變化,說明,angular 不知道值變化了,所以我們可以讓angular 主動(dòng)進(jìn)行變更檢測(cè),讓它知道已經(jīng)發(fā)生了變化。
對(duì)此我們可以使用 ChangeDetectorRef
變化監(jiān)測(cè)類 - ChangeDetectorRef
Angular 在整個(gè)運(yùn)行期間都會(huì)為每一個(gè)組件創(chuàng)建 ChangeDetectorRef 的實(shí)例,該實(shí)例提供了相關(guān)方法來手動(dòng)管理變化監(jiān)測(cè)。有了這個(gè)類,我們自己就可以自定義組件的變化監(jiān)測(cè)策略了,如停止/啟用變化監(jiān)測(cè)或者按指定路徑變化監(jiān)測(cè)等等。
它有以下方法:
- markForCheck():把根組件到該組件之間的這條路徑標(biāo)記起來,通知Angular在下次觸發(fā)變化監(jiān)測(cè)時(shí)必須檢查這條路徑上的組件。
- detach():從變化監(jiān)測(cè)樹中分離變化監(jiān)測(cè)器,該組件的變化監(jiān)測(cè)器將不再執(zhí)行變化監(jiān)測(cè),除非再次手動(dòng)執(zhí)行reattach()方法。
- reattach():把分離的變化監(jiān)測(cè)器重新安裝上,使得該組件及其子組件都能執(zhí)行變化監(jiān)測(cè)。
- detectChanges():手動(dòng)觸發(fā)執(zhí)行該組件到各個(gè)子組件的一次變化監(jiān)測(cè)。
所以,我們可以使用 detectChanges() 來達(dá)到目標(biāo)
使用方法
// 在組件中注入
constructor(private changeDetectorRef: ChangeDetectorRef) {
}
// 直接使用
test() {
this.changeDetectorRef.detectChanges()
}
angular何時(shí)進(jìn)行變化檢測(cè)
總結(jié)起來, 主要有如下幾種情況:
- 用戶輸入操作,比如點(diǎn)擊,提交等
- 請(qǐng)求服務(wù)端數(shù)據(jù)(XHR)
- 定時(shí)事件,比如
setTimeout,setInterval
Angular并不是捕捉對(duì)象的變動(dòng),它采用的是在適當(dāng)?shù)臅r(shí)機(jī)去檢驗(yàn)對(duì)象的值是否被改動(dòng),這個(gè)時(shí)機(jī)就是這些異步事件的發(fā)生。
這個(gè)時(shí)機(jī)是由 Zone.js 去掌控的,它獲取到了整個(gè)應(yīng)用的執(zhí)行上下文,能夠?qū)ο嚓P(guān)的異步事件發(fā)生、完成或者異常等進(jìn)行捕獲,然后驅(qū)動(dòng) Angular 的變化監(jiān)測(cè)機(jī)制執(zhí)行。
Zone.js的作用
實(shí)際上 Zone,js 有一個(gè)叫猴子補(bǔ)丁的東西。在 Zone.js 運(yùn)行時(shí),就會(huì)為這些異步事件做一層代理包裹,也就是說Zone.js運(yùn)行后,調(diào)用 setTimeout、addEventListener 等瀏覽器異步事件時(shí),不再是調(diào)用原生的方法,而是被猴子補(bǔ)丁包裝過后的代理方法。代理里setup了鉤子函數(shù), 通過這些鉤子函數(shù), 可以方便的進(jìn)入異步任務(wù)執(zhí)行的上下文
//以下是Zone.js啟動(dòng)時(shí)執(zhí)行邏輯的抽象代碼片段
function zoneAwareAddEventListener() {...}
function zoneAwareRemoveEventListener() {...}
function zoneAwarePromise() {...}
function patchTimeout() {...}
window.prototype.addEventListener=zoneAwareAddEventListener;
window.prototype.removeEventListener=zoneAwareRemoveEventListener;
window.prototype.promise = zoneAwarePromise;
window.prototype.setTimeout = patchTimeout;
關(guān)于 Zone.js 的詳細(xì)內(nèi)容可以看 這篇文章 。
angular變化檢測(cè)策略
angular 提供了兩種變更檢測(cè)策略,除了上述得Default外還有一種 OnPush 的檢測(cè)機(jī)制
OnPush 與 Default 之間的差別: 當(dāng)檢測(cè)到與子組件輸入綁定的值沒有發(fā)生改變時(shí),變化檢測(cè)就不會(huì)深入到子組件中去 。
一個(gè)OnPush的例子
app.comonent.ts
@Component({
selector: 'app-root',
template: `
<h1>{{title}}</h1>
<h2>user.name: {{user.name}}</h2>
<button type="button" (click)="changeUserName()"> 改變屬性
</button>
<button type="button" (click)="changeUserObject()">
改變對(duì)象
</button>
<app-test [user]="user"></app-test>
`,
})
export class AppComponent {
title = 'OnPush Demo';
user: User = new User({name: 'yunzhi'});
changeUserName() {
this.user.name = 'new name';
}
changeUserObject() {
this.user = new User({name: 'new user'});
}
}
test.component.ts
@Component({
selector: 'app-test',
template: `
<div>
<h3>test 組件</h3>
<p>
<label>User:</label>
<span>{{user.name}}</span>
</p>
</div>`,
// 使用OnPush模式只需要加上下面這段代碼
changeDetection: ChangeDetectionStrategy.OnPush
})
export class TestComponent implements OnInit {
@Input() user: User;
constructor() {
}
ngOnInit() {
}
}
這時(shí)當(dāng)我們點(diǎn)擊改變屬性按鈕時(shí)test組件顯示的并不會(huì)變化,只有改變user得引用test組件顯示的才會(huì)變化,如下圖所示

總結(jié)
本來以為這個(gè)問題沒什么可寫的,直接解決好像就完事了,但沒想到寫著寫著感覺能寫的越來越多,比如 變更檢測(cè)的順序 ,還有 ExpressionChangedAfterItHasBeenCheckedError 都是應(yīng)該知道的問題,但是感覺這些和主題又沒有什么關(guān)系,想了想還是算了。
到此這篇關(guān)于angula中使用iframe點(diǎn)擊后不執(zhí)行變更檢測(cè)的問題的文章就介紹到這了,更多相關(guān)angula iframe 變更檢測(cè)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于AngularJS中ng-repeat不更新視圖的解決方法
今天小編就為大家分享一篇關(guān)于AngularJS中ng-repeat不更新視圖的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-09-09
Angular5中提取公共組件之radio list的實(shí)例代碼
這篇文章主要介紹了Angular5中提取公共組件之radio list的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-07-07
angular或者js怎么確定選中ul中的哪幾個(gè)li
下面小編就為大家?guī)硪黄猘ngular或者js怎么確定選中ul中的哪幾個(gè)li。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08
Angular實(shí)現(xiàn)雙向折疊列表組件的示例代碼
本篇文章主要介紹了Angular實(shí)現(xiàn)雙向折疊列表組件的示例代碼,分為左右兩組,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
詳解創(chuàng)建自定義的Angular Schematics
本文對(duì) Angular Schematics 進(jìn)行了介紹,并創(chuàng)建了一個(gè)用于創(chuàng)建自定義 Component 的 Schematics ,然后在 Angular 項(xiàng)目中以它為模板演練了通過 Schematics 添加自定義的 Component,感興趣的小伙伴們可以參考一下2018-06-06

