[英]Embedding Reactjs in Remote Site iFrame
更新為Bounty
我目前在我的iframe中使用src =“url”來加載對我來說不是最佳的ReactApp,因為這將允許用戶右鍵單擊並“在新窗口中打開”。
我正在尋找的最佳解決方案是將我的bundle.js與一個或類似的解決方案一起寫入iframe。 src將保持為空白,因此用戶無法在新窗口/選項卡中右鍵單擊以打開。
我正在探索如何使用React制作一個可嵌入的小部件,所以我到目前為止從google搜索到了以下內容。 但是,我不渲染,並返回以下消息。
錯誤消息 [錯誤]不變違規:目標容器不是DOM元素。
我使用create-react-app為我的嵌入式應用程序,我只有2個簡單的文件。
index.js
import React from 'react';
import ReactDom from 'react-dom';
import App from './App';
ReactDom.render(
<App />, document.getElementById('root')
)
App.js
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div>This is an embedable widget</div>
)
}
}
export default App;
我創建了一個test.js,它將在遠程iframe中使用下面的簡單代碼調用以生成html,包含js包,以及包含id的div。
這是test.js
//Creates Div
var d = document.createElement("div");
document.body.appendChild(d);
//Creates iFrame
var n = document.createElement("iframe");
n.id = "microcom-frame";
n.style.width = "100%";
n.style.height = "100%";
n.style.background = "transparent";
n.style.position = "relative";
n.style.margin = 0;
n.style.border = "none";
n.style.overflow ="hidden";
n.style.display = "block";
//Append iFrame inside Div
d.appendChild(n);
//Write content to iFrame
n.contentWindow.document.open("text/html", "replace"),
n.contentWindow.document.write("\n <!doctype html>\n <head><script src='http://localhost:3001/static/js/bundle.js' type='text/javascript'></script></head>\n <body><div id='root'></div></body>\n </html>"),
n.contentWindow.document.close();
現在在遠程站點上,我在標題中只有以下腳本來調用上面的test.js。
<script>
(function() {
var d = document,
h = d.getElementsByTagName('head')[0],
s = d.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = 'http://localhost:3001/test.js';
h.appendChild(s);
} )();
</script>
這是......
但是,沒有顯示。
感謝有人可以帶我到下一步。 我正在使用create-react-app創建我的反應文件(這是我學習的唯一方法。)
要滿足Same Origin策略(防止CORS錯誤),請設置<iframe>
的srcdoc
屬性,而不是嘗試write
它。
n.srcdoc = "\n <!doctype html>\n <head><script src='http://localhost:3001/static/js/bundle.js' type='text/javascript'></script></head>\n <body><div id='root'></div></body>\n </html>";
作為額外的好處,您可以使用以下命令禁用右鍵單擊上下文菜單:
n.contentWindow.document.addEventListener("contextmenu", function(e){
e.preventDefault();
return false;
}, false);
這作為一種安全措施是完全沒用的,但它只是作為一個紅鯡魚。 單獨打開框架時顯示的頁面將不包含內容。 只有在用戶想要復制的iframe頁面中沒有任何內容時才能執行此操作; 它並沒有阻止他們這樣做,但如果你想復制一些東西,那真的很煩人。
演示:
//Creates Div var d = document.createElement("div"); document.body.appendChild(d); //Creates iFrame var n = document.createElement("iframe"); n.id = "microcom-frame"; n.style.width = "100%"; n.style.height = "100%"; n.style.background = "transparent"; n.style.position = "relative"; n.style.margin = 0; n.style.border = "none"; n.style.overflow ="hidden"; n.style.display = "block"; //Append iFrame inside Div d.appendChild(n); //Write content to iFrame n.srcdoc = "<!doctype html><html><head></head><body><div id='root'>Example content</div></body></html>";
出於安全目的,嵌入iframe不是一個好習慣,如果使用沙盒iframe可能會更好。
在測試環境中的DOM中讀取目標div之前的腳本,只需更改標記的順序即可。 請參閱下文並查看底部的其他問題,當您移動到野外時,您可能會嘗試做什么。
將“async defer”添加到您在初始代碼中插入iframe的腳本標記中,如下所示:
n.contentWindow.document.write("\n <!doctype html>\n <head><script async defer src='http://localhost:3001/static/js/bundle.js' type='text/javascript'></script></head>\n <body><div id='root'></div></body>\n </html>"),
您可以在您插入的正文的末尾添加腳本標記(或者執行展位並將異步延遲放在其上)
嘗試使用srcdoc,它工作得更好,因為它甚至沒有提供突破框架的選項(它只是重新加載上面示例中的當前位置)
n.srcdoc = "\n <!doctype html>\n <head></head>\n <body><div id='root'></div><script async defer src='http://localhost:3001/static/js/bundle.js' type='text/javascript'></script></body>\n </html>"
然而。
當我在生產中嘗試這個時,它沒有加載我的整個應用程序。 除了構建中的/ static文件夾中的初始js包之外的任何其他內容都不會加載,因為應用程序會相對於小部件位置查找它們。
你可以通過確保js沒有塊來解決這個問題(創建反應應用程序不應該分割你的代碼,除非你使用一個包專門做那個)。 您還需要在應用程序外部加載所有css文件和圖像,而不是導入它們。
也可以使用其中一種方法將react應用程序部署到子目錄中,以便為應用程序的靜態資源設置絕對基本URL。
另外,您可能希望在使用它時從react應用程序中的index.js中刪除registerServiceWorker()。
如果仍然會導致問題並且您需要通過src加載它,您可以讓react應用程序檢查它是否不在框架內並自行終止或在此處的某些方法無框架時返回如何識別是否正在加載網頁在iframe內部或直接進入瀏覽器窗口?
您已在index.js中使用root作為目標容器。 可能這不是index.html文件中DOM元素的名稱。 使它一樣,也許它會起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.