"長時間不寫文章,開頭的方式總是那麼出奇的相似",最近很忙,好久沒寫博客了啊(是不是?)。
更換工作已經有三個月有餘,這段三個月把過去三年沒加過的班都加了一次。收穫挺多,發現的問題也挺多。
一直也在思考一些問題:
如何把自己遇見的問題好好的理解並且總結?
如何很好的學習新知識,不只是停留在用的基礎上?
……
上面的問題我一直在嘗試更適合我的方法,暫時就不扯淡了,先嚐試一下把這段時間過程中遇見的問題總結下,然後爭取給看文的你以我的方式描述清楚,我想我應該就把第一個問題解決了。
簡介
項目實戰中postMessage
的使用
問題描述
前提:我們的項目與兄弟團隊的項目都是基於同一套基礎框架開發,只是在視圖層我們有各自的一套東西。
項目是一個hybrid項目,目前是以h5的形式在開發,後期可以輕鬆轉爲hybrid。目前已經以h5的形式上線到自家公衆號,大致是在硬件上產出一份報告,h5把報告的內容展示出來。
新需求是,把報告推給兄弟團隊的APP,在APP內也能打開我們的報告進行查看報告然後點評。
兄弟團隊爲了最小的改動實現這個功能,用了iframe的形式打開我們推過去的報告鏈接,問題就出在報告能在兄弟團隊的APP中打開卻不能跳轉鏈接,問題是因爲我們的基礎框架提供的forward
方法在app內是通過native的方式來跳轉,但是我們的協議不會被兄弟團隊的app識別,簡單說就是跳轉直接被攔截了。
經過幾番商量,商定出三個解決方案:
- iframe跨域通信
- 他們重新做一套(不可取的備選)
- 我們來實現他們的點評業務(業務交錯不可取)
雜貨鋪中的知識點
很明顯我們更傾向於第一種方式,彷彿記得之前總結過類似的一篇文章同源策略和跨域知識點學習,當時完全是參考知識點進行的一次搬移,現在看來完全還是沒有透徹理解。
- 同源:同源即需要協議主機名(域名或者ip)端口相同。
- 跨域:域名不一致了,自然是不同源的,這種情況下要通信何解呢?
postMessage
派上用途。
h5模式下子頁面跳轉協議可以正常使用history模式或者非單頁模式跳轉。(知識點:這種情況下iframe的src不會隨iframe內跳轉鏈接的變化而變化,父頁面不能監聽到子頁面內的頁面變化)
hybrid模式下鏈接跳轉被攔截,頁面表現就是鏈接點不了,如何讓父元素知道我點了什麼鏈接,然後來切換頁面,他們做url更換,來實現跳轉並且支持切換頁面操作,如此我們就需要子頁面給父頁面發送一條message
告訴它我要跳轉到哪一個頁面。
實戰知識點
頁面跳轉中我們使用了$forward
方法進行收口,所有的跳轉都需要經過這個方法(對於收口的好處這裏就體現出來了),我只需要判斷ua
在跳轉前執行以下消息發送的方法。
/**
* 頁面跳轉方法
* @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內做特殊處理
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
事件獲取我傳遞過去的消息做特殊處理即可
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/