angula中使用iframe點擊后不執(zhí)行變更檢測的問題
這個問題是上周的,當時覺得這個問題的解決辦法太簡單了,不用寫博客記錄,但是潘老師今天今天又遇到了需要使用這個的地方,感覺問題雖然不難,但是,寫篇博客,方便自己查詢,也給了其他人搜索到解決辦法的機會。
問題描述
項目中使用到了ifame,理想狀態(tài)是:當點擊ifame中的按鈕時,將會調用通過angular寫的一個函數,函數將會修改一個ngif的判斷條件,顯示一個彈窗,
但現(xiàn)實是:當點擊ifame中的按鈕時,將會調用通過angular寫的一個函數,函數將會修改一個ngif的判斷條件,然后就沒有然后了.
開始的時候自己直接懵了, 方法確實執(zhí)行了, 但界面沒修改, 問了問潘老師, 潘老師說看看生命周期函數是否執(zhí)行了, 果然, 所有的生命周期函數都沒有調用。
解決辦法
既然生命周期函數沒調用,我們讓他調用不就行了,值已經變化了,但是界面不變化,說明,angular 不知道值變化了,所以我們可以讓angular 主動進行變更檢測,讓它知道已經發(fā)生了變化。
對此我們可以使用 ChangeDetectorRef
變化監(jiān)測類 - ChangeDetectorRef
Angular 在整個運行期間都會為每一個組件創(chuàng)建 ChangeDetectorRef 的實例,該實例提供了相關方法來手動管理變化監(jiān)測。有了這個類,我們自己就可以自定義組件的變化監(jiān)測策略了,如停止/啟用變化監(jiān)測或者按指定路徑變化監(jiān)測等等。
它有以下方法:
- markForCheck():把根組件到該組件之間的這條路徑標記起來,通知Angular在下次觸發(fā)變化監(jiān)測時必須檢查這條路徑上的組件。
- detach():從變化監(jiān)測樹中分離變化監(jiān)測器,該組件的變化監(jiān)測器將不再執(zhí)行變化監(jiān)測,除非再次手動執(zhí)行reattach()方法。
- reattach():把分離的變化監(jiān)測器重新安裝上,使得該組件及其子組件都能執(zhí)行變化監(jiān)測。
- detectChanges():手動觸發(fā)執(zhí)行該組件到各個子組件的一次變化監(jiān)測。
所以,我們可以使用 detectChanges()
來達到目標
使用方法
// 在組件中注入 constructor(private changeDetectorRef: ChangeDetectorRef) { } // 直接使用 test() { this.changeDetectorRef.detectChanges() }
angular何時進行變化檢測
總結起來, 主要有如下幾種情況:
- 用戶輸入操作,比如點擊,提交等
- 請求服務端數據(XHR)
- 定時事件,比如
setTimeout
,setInterval
Angular并不是捕捉對象的變動,它采用的是在適當的時機去檢驗對象的值是否被改動,這個時機就是這些異步事件的發(fā)生。
這個時機是由 Zone.js
去掌控的,它獲取到了整個應用的執(zhí)行上下文,能夠對相關的異步事件發(fā)生、完成或者異常等進行捕獲,然后驅動 Angular 的變化監(jiān)測機制執(zhí)行。
Zone.js的作用
實際上 Zone,js
有一個叫猴子補丁的東西。在 Zone.js
運行時,就會為這些異步事件做一層代理包裹,也就是說Zone.js運行后,調用 setTimeout、addEventListener
等瀏覽器異步事件時,不再是調用原生的方法,而是被猴子補丁包裝過后的代理方法。代理里setup了鉤子函數, 通過這些鉤子函數, 可以方便的進入異步任務執(zhí)行的上下文
//以下是Zone.js啟動時執(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;
關于 Zone.js
的詳細內容可以看 這篇文章 。
angular變化檢測策略
angular 提供了兩種變更檢測策略,除了上述得Default外還有一種 OnPush
的檢測機制
OnPush 與 Default 之間的差別: 當檢測到與子組件輸入綁定的值沒有發(fā)生改變時,變化檢測就不會深入到子組件中去 。
一個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()"> 改變對象 </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() { } }
這時當我們點擊改變屬性按鈕時test組件顯示的并不會變化,只有改變user得引用test組件顯示的才會變化,如下圖所示
總結
本來以為這個問題沒什么可寫的,直接解決好像就完事了,但沒想到寫著寫著感覺能寫的越來越多,比如 變更檢測的順序
,還有 ExpressionChangedAfterItHasBeenCheckedError
都是應該知道的問題,但是感覺這些和主題又沒有什么關系,想了想還是算了。
到此這篇關于angula中使用iframe點擊后不執(zhí)行變更檢測的問題的文章就介紹到這了,更多相關angula iframe 變更檢測內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Angularjs中如何使用filterFilter函數過濾
這篇文章主要介紹了Angularjs中如何使用filterFilter函數過濾的相關資料,需要的朋友可以參考下2016-02-02利用Angularjs中模塊ui-route管理狀態(tài)的方法
這篇文章主要給大家介紹了如何用Angularjs中的模板ui-route來管理狀態(tài)的方法,文中通過示例代碼介紹的很詳細,相信對大家的理解和學習具有一定的參考借鑒價值,有需要的朋友可以一起來學習學習。2016-12-12AngularJS實現(xiàn)的鼠標拖動畫矩形框示例【可兼容IE8】
這篇文章主要介紹了AngularJS實現(xiàn)的鼠標拖動畫矩形框,涉及基于AngularJS的事件響應及頁面元素屬性動態(tài)操作相關實現(xiàn)技巧,需要的朋友可以參考下2019-05-05angularJS?實現(xiàn)長按不觸發(fā)點擊事件可以復制剪貼方法
這篇文章主要為大家介紹了angularJS實現(xiàn)長按不觸發(fā)點擊事件可以復制剪貼方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06AngularJS實現(xiàn)單一頁面內設置跳轉路由的方法
這篇文章主要介紹了AngularJS實現(xiàn)單一頁面內設置跳轉路由的方法,結合實例形式分析了AngularJS路由操作相關設置與使用技巧,需要的朋友可以參考下2017-06-06