iframe跨域通訊實戰

"長時間不寫文章,開頭的方式老是那麼出奇的類似",最近很忙,很久沒寫博客了啊(是否是?)。
更換工做已經有三個月有餘,這段三個月把過去三年沒加過的班都加了一次。收穫挺多,發現的問題也挺多。
一直也在思考一些問題:
如何把本身碰見的問題好好的理解而且總結?
如何很好的學習新知識,不僅是停留在用的基礎上?
……segmentfault

上面的問題我一直在嘗試更適合個人方法,暫時就不扯淡了,先嚐試一下把這段時間過程當中碰見的問題總結下,而後爭取給看文的你以個人方式描述清楚,我想我應該就把第一個問題解決了。跨域

簡介

項目實戰中postMessage的使用app

問題描述

前提:咱們的項目與兄弟團隊的項目都是基於同一套基礎框架開發,只是在視圖層咱們有各自的一套東西。
項目是一個hybrid項目,目前是以h5的形式在開發,後期能夠輕鬆轉爲hybrid。目前已經以h5的形式上線到自家公衆號,大體是在硬件上產出一份報告,h5把報告的內容展現出來。
新需求是,把報告推給兄弟團隊的APP,在APP內也能打開咱們的報告進行查看報告而後點評。
兄弟團隊爲了最小的改動實現這個功能,用了iframe的形式打開咱們推過去的報告連接,問題就出在報告能在兄弟團隊的APP中打開卻不能跳轉連接,問題是由於咱們的基礎框架提供的forward方法在app內是經過native的方式來跳轉,可是咱們的協議不會被兄弟團隊的app識別,簡單說就是跳轉直接被攔截了。
通過幾番商量,商定出三個解決方案:框架

  • iframe跨域通訊
  • 他們從新作一套(不可取的備選)
  • 咱們來實現他們的點評業務(業務交錯不可取)

雜貨鋪中的知識點

很明顯咱們更傾向於第一種方式,彷彿記得以前總結過相似的一篇文章同源策略和跨域知識點學習,當時徹底是參考知識點進行的一次搬移,如今看來徹底仍是沒有透徹理解。post

  • 同源:同源即須要協議主機名(域名或者ip)端口相同。
  • 跨域:域名不一致了,天然是不一樣源的,這種狀況下要通訊何解呢?

postMessage派上用途。
h5模式下子頁面跳轉協議能夠正常使用history模式或者非單頁模式跳轉。(知識點:這種狀況下iframe的src不會隨iframe內跳轉連接的變化而變化,父頁面不能監聽到子頁面內的頁面變化)
hybrid模式下連接跳轉被攔截,頁面表現就是連接點不了,如何讓父元素知道我點了什麼連接,而後來切換頁面,他們作url更換,來實現跳轉而且支持切換頁面操做,如此咱們就須要子頁面給父頁面發送一條message告訴它我要跳轉到哪個頁面。學習

實戰知識點

頁面跳轉中咱們使用了$forward方法進行收口,全部的跳轉都須要通過這個方法(對於收口的好處這裏就體現出來了),我只須要判斷ua在跳轉前執行如下消息發送的方法。this

/**
 * 頁面跳轉方法
 * @param page 要跳轉的頁面名稱
 * @param param 跳轉時須要額外攜帶的參數
 */
$forward(page, param) {
    // _ extend getUrlParam getUrlRule loadPage isHybrid 省略
    var param = _.extend(_.getUrlParam(), param);
    let url = _.getUrlRule(page, param);
    if(isHybrid) {
        _.requestHybrid({
            // 省略
        });
    } else {
        _.loadPage(url);
    }
}

在跳轉前咱們先檢測一下ua,判斷是不是在兄弟團隊app內作特殊處理url

let ua = navigator.userAgent.toLowerCase(),
    isFriendHybrid = /friend_hybrid_\w+_(\d*\.?)+/.test(ua);
if(isFriendHybrid) {
    window.top.postMessage({
        tag: 'forward',
        url: url
    }, '*')
} else {
    this.$forward();
}

在兄弟團隊的父頁面只須要監聽message事件獲取我傳遞過去的消息作特殊處理便可.net

window.addEventListener('message', function(e) {
    console.log(e.data);
    // {tag: 'forward', url: ……}
})

例如在一個特殊位置我會在沒有pdf的時候直接彈出調試「暫時沒有報告」,用戶點擊之際顯示的是我彈出的toast,因爲嵌入後有兼容問題,因而咱們又約定了一個方法。調試

window.top.postMessage({
    tag: 'showtoast',
    content: '暫時沒有報告'
}, '*')

這應該就是一個典型的iframe跨域通訊例子。

demo

https://jsfiddle.net/unofficial/xwaksbvn/

相關文章
相關標籤/搜索