歡迎您光臨本站 註冊首頁

angula中使用iframe點選後不執行變更檢測的問題

←手機掃碼閱讀     火星人 @ 2020-05-11 , reply:0

這個問題是上週的,當時覺得這個問題的解決辦法太簡單了,不用寫部落格記錄,但是潘老師今天今天又遇到了需要使用這個的地方,感覺問題雖然不難,但是,寫篇部落格,方便自己查詢,也給了其他人搜尋到解決辦法的機會。
問題描述
專案中使用到了ifame,理想狀態是:當點選ifame中的按鈕時,將會呼叫通過angular寫的一個函式,函式將會修改一個ngif的判斷條件,顯示一個彈窗,
但現實是:當點選ifame中的按鈕時,將會呼叫通過angular寫的一個函式,函式將會修改一個ngif的判斷條件,然後就沒有然後了.
開始的時候自己直接懵了, 方法確實執行了, 但介面沒修改, 問了問潘老師, 潘老師說看看生命週期函式是否執行了, 果然, 所有的生命週期函式都沒有呼叫。
解決辦法
既然生命週期函式沒呼叫,我們讓他呼叫不就行了,值已經變化了,但是介面不變化,說明,angular 不知道值變化了,所以我們可以讓angular 主動進行變更檢測,讓它知道已經發生了變化。
對此我們可以使用 ChangeDetectorRef
變化監測類 - ChangeDetectorRef
Angular 在整個執行期間都會為每一個元件建立 ChangeDetectorRef 的例項,該例項提供了相關方法來手動管理變化監測。有了這個類,我們自己就可以自定義元件的變化監測策略了,如停止/啟用變化監測或者按指定路徑變化監測等等。
它有以下方法:
markForCheck():把根元件到該元件之間的這條路徑標記起來,通知Angular在下次觸發變化監測時必須檢查這條路徑上的元件。
detach():從變化監測樹中分離變化監測器,該元件的變化監測器將不再執行變化監測,除非再次手動執行reattach()方法。
reattach():把分離的變化監測器重新安裝上,使得該元件及其子元件都能執行變化監測。
detectChanges():手動觸發執行該元件到各個子元件的一次變化監測。
所以,我們可以使用 detectChanges() 來達到目標
使用方法
// 在元件中注入 constructor(private changeDetectorRef: ChangeDetectorRef) { } // 直接使用 test() { this.changeDetectorRef.detectChanges() }
angular何時進行變化檢測
總結起來, 主要有如下幾種情況:
使用者輸入操作,比如點選,提交等
請求服務端資料(XHR)
定時事件,比如 setTimeout , setInterval
Angular並不是捕捉物件的變動,它採用的是在適當的時機去檢驗物件的值是否被改動,這個時機就是這些非同步事件的發生。
這個時機是由 Zone.js 去掌控的,它獲取到了整個應用的執行上下文,能夠對相關的非同步事件發生、完成或者異常等進行捕獲,然後驅動 Angular 的變化監測機制執行。
Zone.js的作用
實際上 Zone,js 有一個叫猴子補丁的東西。在 Zone.js 執行時,就會為這些非同步事件做一層代理包裹,也就是說Zone.js執行後,呼叫 setTimeout、addEventListener 等瀏覽器非同步事件時,不再是呼叫原生的方法,而是被猴子補丁包裝過後的代理方法。代理裡setup了鉤子函式, 通過這些鉤子函式, 可以方便的進入非同步任務執行的上下文
//以下是Zone.js啟動時執行邏輯的抽象程式碼片段 function zoneAwareAddEventListener() {...} function zoneAwareRemoveEventListener() {...} function zoneAwarePromise() {...} function patchTimeout() {...} window.prototype.addEventListener=zoneAwareAddEventListener; window.prototype.removeEventListener=zoneAwareRemoveEventListener; window.prototype.promise = zoneAwarePromise; window.prototype.setTimeout = patchTimeout;
關於 Zone.js 的詳細內容可以看 這篇文章 。
angular變化檢測策略
angular 提供了兩種變更檢測策略,除了上述得Default外還有一種 OnPush 的檢測機制
OnPush 與 Default 之間的差別: 當檢測到與子元件輸入繫結的值沒有發生改變時,變化檢測就不會深入到子元件中去 。
一個OnPush的例子
app.comonent.ts
@Component({ selector: 'app-root', template: `

{{title}}

user.name: {{user.name}}

`, }) 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: `

test 元件

User:{{user.name}}

`, // 使用OnPush模式只需要加上下面這段程式碼 changeDetection: ChangeDetectionStrategy.OnPush }) export class TestComponent implements OnInit { @Input() user: User; constructor() { } ngOnInit() { } }
這時當我們點選改變屬性按鈕時test元件顯示的並不會變化,只有改變user得引用test元件顯示的才會變化,如下圖所示
總結
本來以為這個問題沒什麼可寫的,直接解決好像就完事了,但沒想到寫著寫著感覺能寫的越來越多,比如 變更檢測的順序 ,還有 ExpressionChangedAfterItHasBeenCheckedError 都是應該知道的問題,但是感覺這些和主題又沒有什麼關係,想了想還是算了。



[火星人 ] angula中使用iframe點選後不執行變更檢測的問題已經有118次圍觀

http://coctec.com/docs/program/show-post-233772.html