透過postMessage完成兩個分頁之間資料互相傳輸

最近有個需求
大概是主要畫面為輸入表單(母頁面),輸入完成後,會把資料存放到List,要查看時就透過Modal彈跳視窗顯示(子頁面)。
但User有新需求為想要邊編輯表單資料又可以同時看到資料List,那麼就不能用Modal彈跳視窗的方式來完成。
因為Modal彈跳視窗其實是個遮罩,會造成遮罩後的頁面功能無法使用。
勢必要用兩個分頁來處理,但主.次頁面之間會有資料互相傳遞,這時就能透過postMessage這個API來處理

1.首先先建立兩個Component分別代表母.子頁面

主要視窗
次要視窗(新分頁)

 


2.主畫面ts & html程式如下(程式碼不是完整的,直接使用可能會有錯誤)


{{getData | json}}
<input #_txt_user_name type="hidden" value={{inputUserName}}>
<button (click)="openWindow()">新分頁開啟</button>
<input #_txt_test type="text">
<button (click)="postData()">傳遞資料給次要視窗</button>
  getData: string;
  previewWindow: Window; // 記錄開啟的 window 物件
  
  @HostListener('window:message', ['$event'])
  onMessage(event: MessageEvent): void
  {
    this.getData = event.data;
  }
  
  openWindow(): void
  {
    // 開啟目標視窗,如視窗未完成開啟前即執行 postMessage() 會傳送無效
    this.previewWindow = window.open('temp_list_modal', "mozillaWindow", "popup");
  }

  postData(): void {
    debugger;
    const foo = {
      foo1: 'aaa',
      foo2: 123,
      val: this.boxInForm.controls["txt_test "].value
    };

    if (this.previewWindow) {
      // 第二個參數 targetOrigin 為了示範使用故不指定,實務上應設定信任網域防止資訊外洩
      this.previewWindow.postMessage(foo, 'http://localhost:4200/temp_list_modal');
    }
  }

2.次要畫面ts & html程式如下(程式碼不是完整的,直接使用可能會有錯誤),這裡要注意的是母頁面為既有頁面,不用使用window.open開啟,我們這裡使用window.opener。

<p>test works!</p>
<!-- 印出資料 -->
{{passData | json}}
<button (click)="passDataToParent()">回傳資料給主要視窗</button>

  passData: string;
  previewWindow: Window; // 記錄開啟的 window 物件
  
  /*監聽主畫面傳過來的資料*/
  @HostListener('window:message', ['$event'])
  onMessage(event: MessageEvent): void
  {
    this.passData = event.data;
  }
  
  passDataToParent()
  {
    if (this.passData)
    {
      window.opener.postMessage(this.passData, 'http://localhost:4200');
    }
  }

4.進行測試(母=>子)
 

輸入測試字串後,點選傳遞資料給次要視窗
子頁面收到母頁面傳來的資料了

4.進行測試(子=>母)
 

點回傳資料給主要視窗
母頁面也收到子頁面傳來的資料了

 

Ref:
1.[Angular] 使用 window.postMessage() 實作跨網域傳值
2.postMessage: communication between browser tabs
3.那些被忽略但很好用的 Web API / PostMessage