axios 警告:validateDOMNesting(...):不能< html>作为孩子出现,< div>

gev0vcfq  于 2023-10-18  发布在  iOS
关注(0)|答案(1)|浏览(200)

[Edit:我也尝试了使用错误的SetInnerHTML代码,解决了validateDOMNesting问题,但仍然没有交互性,我猜JavaScript代码被禁用或不工作]
所以我从后端获取一个文件,并在我的React应用程序中呈现它。我正在获取的文件是游戏文件,如井字游戏,石头剪刀布,等等,所有这些游戏都是用html和js构建的。问题是,当我渲染html文件时,处理程序不工作,例如在井字游戏中,我有处理点击的函数,在用户点击一个点后,它的innerHtml被设置为X或O,但这些处理程序不工作,并且发生错误:我在下面附上代码和截图

  1. default function RenderGame({ game }) {
  2. return (
  3. <>
  4. <div>
  5. {ReactHtmlParser(game)}
  6. </div>
  7. </>
  8. )
  9. }
  10. const PlayGame = ({ temp }) => {
  11. const [game, setGame] = useState({})
  12. const params = useParams()
  13. const gameID = <params className="id"></params>
  14. useQuery(`project-${gameID}`, async () => {
  15. const resp = await axios.get(`${import.meta.env.VITE_API_URL}/projects/${gameID}/iframe`)
  16. console.log(resp)
  17. return resp.data
  18. }, {
  19. onSuccess: (data) => {
  20. setGame(data)
  21. }
  22. })
  23. const handleDestroy = (e) => {
  24. e.preventDefault()
  25. deleteGame.mutate()
  26. }
  27. return (
  28. <RenderGame game={game}></RenderGame>
  29. )
  30. }
  31. export default PlayGame;

游戏的代码如下:

  1. "<!-- app/views/projects/iframe.html.erb -->
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <!-- Add the base tag here only if there are image files -->
  6. <base href="/uploads/image_folder_1693815923/">
  7. </head>
  8. <body>
  9. <!-- Render the HTML content -->
  10. <div class="message-code">
  11. <!DOCTYPE html>
  12. <html>
  13. <head>
  14. <style>
  15. *{
  16. margin: 0;
  17. padding: 0;
  18. background-color: black
  19. }
  20. .title{
  21. text-align: center;
  22. margin-bottom: 0px;
  23. color: #808080;
  24. font-style: italic;
  25. font-weight: bold;
  26. }
  27. .gameContainer{
  28. display: flex;
  29. justify-content: center;
  30. padding-top: 20px;
  31. }
  32. .container{
  33. display: grid;
  34. grid-template-rows: repeat(3, 10vw);
  35. grid-template-columns: repeat(3, 10vw);
  36. position: relative;
  37. justify-content: center;
  38. }
  39. .box{
  40. border: 2px solid #C0C0C0;
  41. font-size: 6vw;
  42. cursor: pointer;
  43. display: flex;
  44. justify-content: center;
  45. align-items: center;
  46. }
  47. .box:hover{
  48. background-color: #191919;
  49. }
  50. .info {
  51. font-size: 28px;
  52. color: #A0A0A0;
  53. text-align: center;
  54. font-style: italic;
  55. }
  56. .player {
  57. text-align: center;
  58. }
  59. .gameInfo{
  60. padding: 30px 34px;
  61. text-align: center;
  62. }
  63. .btn{
  64. margin-top: 4px;
  65. cursor: pointer;
  66. }
  67. .line{
  68. background-color: black;
  69. height: 3px;
  70. width: 0;
  71. position: absolute;
  72. background-color: #911d91;
  73. transition: width 0.3s ease-in-out;
  74. text-align:center;
  75. }
  76. .boxtext{
  77. color: white;
  78. background-color: transparent;
  79. }
  80. </style>
  81. </head>
  82. <body>
  83. <h1 class="title">Welcome To Tic Tac Toe</h1>
  84. <div class="player">
  85. <span class="info">Turn for: X</span>
  86. </div>
  87. <div class="gameContainer">
  88. <div class="container">
  89. <div class="line"></div>
  90. <div class="box border-top-0 border-left-0"><span class="boxtext"></span></div>
  91. <div class="box border-top-0"><span class="boxtext"></span></div>
  92. <div class="box border-top-0 border-right-0"><span class="boxtext"></span></div>
  93. <div class="box border-left-0"><span class="boxtext"></span></div>
  94. <div class="box"><span class="boxtext"></span></div>
  95. <div class="box border-right-0"><span class="boxtext"></span></div>
  96. <div class="box border-bottom-0 border-left-0"><span class="boxtext"></span></div>
  97. <div class="box border-bottom-0"><span class="boxtext"></span></div>
  98. <div class="box border-bottom-0 border-right-0"><span class="boxtext"></span></div>
  99. </div>
  100. </div>
  101. <div class="gameInfo">
  102. <button id="reset" class="btn btn-secondary btn-lg">Start New Game</button>
  103. </div>
  104. <script>
  105. function initializetictactoe(){
  106. let turn = "X"
  107. let isgameover = false;
  108. const changeTurn = ()=>{
  109. return turn === "X"? "0": "X"
  110. }
  111. const checkWin = ()=>{
  112. let boxtext = document.getElementsByClassName('boxtext');
  113. let wins = [
  114. [0, 1, 2, 5, 5, 0],
  115. [3, 4, 5, 5, 15, 0],
  116. [6, 7, 8, 5, 25, 0],
  117. [0, 3, 6, -5, 15, 90],
  118. [1, 4, 7, 5, 15, 90],
  119. [2, 5, 8, 15, 15, 90],
  120. [0, 4, 8, 5, 15, 45],
  121. [2, 4, 6, 5, 15, 135],
  122. ]
  123. wins.forEach(e =>{
  124. if((boxtext[e[0]].innerText === boxtext[e[1]].innerText) && (boxtext[e[2]].innerText === boxtext[e[1]].innerText) && (boxtext[e[0]].innerText !== "") ){
  125. document.querySelector('.info').innerText = boxtext[e[0]].innerText + " Won"
  126. isgameover = true
  127. document.querySelector(".line").style.transform = `translate(${e[3]+29}vw, ${e[4]}vw) rotate(${e[5]}deg)`
  128. document.querySelector(".line").style.width = "20vw";
  129. setTimeout(function() {
  130. if (confirm(turn+' Lose! Play Again?')) {
  131. location.reload();
  132. } else {
  133. window.location.href = '<%= user_path(current_user.id) %>';
  134. }
  135. }, 400);
  136. }
  137. })
  138. }
  139. let boxes = document.getElementsByClassName("box");
  140. Array.from(boxes).forEach(element =>{
  141. let boxtext = element.querySelector('.boxtext');
  142. element.addEventListener('click', ()=>{
  143. if(boxtext.innerText === ''){
  144. boxtext.innerText = turn;
  145. turn = changeTurn();
  146. checkWin();
  147. if (!isgameover){
  148. document.getElementsByClassName("info")[0].innerHTML = "Turn for<strong>: " + turn + "</strong>";
  149. }
  150. }
  151. })
  152. })
  153. reset.addEventListener('click', ()=>{
  154. let boxtexts = document.querySelectorAll('.boxtext');
  155. Array.from(boxtexts).forEach(element => {
  156. element.innerText = ""
  157. });
  158. turn = "X";
  159. isgameover = false
  160. document.querySelector(".line").style.width = "0vw";
  161. document.getElementsByClassName("info")[0].innerText = "Turn for " + turn;
  162. })
  163. }
  164. initializetictactoe();
  165. </script>
  166. </body>
  167. </div>
  168. </body>
  169. </html>
  170. "

guykilcj

guykilcj1#

我认为你可以再次尝试使用SetInnerHTML,但这一次,尝试使用srcdoc(而不是src)属性将游戏HTML放入<iframe>中。srcdoc属性让您指定要在<iframe>中显示的HTML。
下面是我做的一个CodePen演示用法(如果它一开始没有正确加载,用Ctrl+Shift+7重新加载代码。我不知道它为什么会这样做,但当我在桌面上尝试本地React项目中的代码时,它运行得很好):https://codepen.io/SonicBoomNFA/pen/eYbbQLy
getGame()模拟检索游戏的HTML。它返回测试两个事件侦听器的普通HTML(一个使用onclick属性直接在黄色正方形上,另一个使用addEventListener()<body>下面使用<script>标记)。我还对字符串调用sanitize(),它将游戏HTML中的所有双引号替换为&quot;,因为嵌套的双引号会破坏代码。
<iframe>上的onload属性调整iframe的大小以适应其内容(受此Adjust width and height of iframe to fit with content in it的启发)。

相关问题