這是近期個人在開發chrome外掛時的其中一個小總結。還有很多沒有總結出來。因為目前外掛還在迭代中,(herry菌外掛,用於B站C站),屬於個人業餘的一個小專案。還有很多功能沒有實現,以及還需要再看能加上什麼功能。
封裝的postMessage庫 herryPostMessage.js
(function (w) { //herry物件 w.herry = {}; //iframe的id if(!herry.iframeId) { herry.iframeId = 'iframe' } //父視窗名字 if(!herry.parentName) { herry.parentName = '父視窗' } //子視窗名字 if(!herry.childName) { herry.childName = '子視窗' } //跨域物件 const messageObj = {}; //父頁面 /** * 傳送給子頁面資料 */ const postMessage = (data, fn = null) => { const iframe = document.getElementById(herry.iframeId) iframe.contentWindow.postMessage( { name: herry.parentName, //父頁面名字 ...data, }, "*" ); messageObj[data.action] = fn; }; /** * 監聽子頁面返回的資料 */ w.addEventListener( "message", (event) => { const { data } = event; if (data && typeof data === "object" && data.name === herry.childName) { messageObj[data.action](data); } }, false ); //子頁面 /** * 返回資料給父頁面 參1=當前action 參2=返回的資料 */ const returnData = (action, data) => { top.postMessage( { name: herry.childName, //子頁面名字 action, data, }, "*" ); }; /** * 監聽父頁面傳送的資料 */ w.addEventListener( "message", async (event) => { const { data } = event; if (data && typeof data === "object" && data.name === herry.parentName) { if (herry.callback) { herry.callback(data) } } }, false ); herry.postMessage = postMessage; herry.returnData = returnData; })(window);
使用這個庫讓a域名下獲取b域名下的資料,即a發出請求,b返回給a資料。a是父頁面,b是子頁面
使用:
域名a和b的頁面上都需要引入herryPostMessage.js
a頁面處理(父頁面):
加入iframe(src是b域名的頁面,需要設定一個id,一般也可以將iframe使用樣式隱藏掉)。
<iframe src="//b.com/xxx.html" id="ifr" frameborder="0" ></iframe>
設定iframeId=上面的這個id:
herry.iframeId = "ifr";
發起請求(action是設定的一個請求名,在b頁面中進行匹配用。後面的資料是攜帶給b頁面用的引數。後面的res是b頁面執行後的回撥函式,可進行處理b返回的資料):
herry.postMessage({ action:'geta1', x: 1 }, (res) => {
console.log(res.data);
});
b頁面處理(子頁面):
b頁面的herry.callback通過action匹配執行,並做處理,通過herry.returnData將資料返回給a的回撥函式。即實現了互動。
herry.callback = async (data) => { if (data.action === "geta1") { //... herry.returnData(data.action, { x: 2 }); } //... };
不過這種封裝方式也不是特別好,有侷限性,比如b(子頁面)像a(父頁面)發起請求還是比較麻煩。歡迎各位提出意見或建議。