<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      一個神奇的JS代碼,讓瀏覽器在新的空白標簽頁運行我們 HTML 代碼(createObjectURL 的妙用)

      前言

      目前,網上很多在線運行 HTML 的頁面,大都是這樣的邏輯:

      上面一個代碼框 <textera> ,下面一個 <iframe>,然后通過 js,將我們的代碼框中的 HTML 給輸入到 <iframe> 里面,這便是一個簡單的在線運行 html 的邏輯。

      甚至我們可以在一行里寫一個在線運行 html 的頁面。比如下面這個,一個高度精簡的簡短的 HTML JS CSS代碼:

      <body oninput="i.srcdoc=h.value+'<style>'+c.value+'</style><script>'+j.value+'</script>'"><style>textarea,iframe{width:100%;height:50%}body{margin:0}textarea{width:33.33%;font-size:18}</style><textarea placeholder=HTML id=h></textarea><textarea placeholder=CSS id=c></textarea><textarea placeholder=JS id=j></textarea><iframe id=i>
      

      如果想運行,很簡單,將下面這個代碼直接粘貼到瀏覽器框里,并回車即可:

      data:text/html,<body oninput="i.srcdoc=h.value+'<style>'+c.value+'</style><script>'+j.value+'</script>'"><style>textarea,iframe{width:100%;height:50%}body{margin:0}textarea{width:33.33%;font-size:18}</style><textarea placeholder=HTML id=h></textarea><textarea placeholder=CSS id=c></textarea><textarea placeholder=JS id=j></textarea><iframe id=i>
      

      效果如下

      image

      上面三個框分別是 HTML CSS JS 代碼,直接通過 i.srcdoc=h.value+'<style>'+c.value+'</style><script>'+j.value+'</script> 這樣一行 js 便賦予給了 <iframe>,然后就能在線運行我們的 前端代碼 了。

      原理就是這樣,無論是菜鳥教程里的代碼運行框,還是大名鼎鼎的 codepen.io 這種代碼分享庫,其原理都差不多。

      image

      看,長的一模一樣。

      問題

      但這個時候,就出現了一個問題。

      我們有可能,不喜歡在一個頁面里夾雜著另一個頁面,感覺太悶了,如果 HTML 代碼是在一個新的頁面運行里就好了。其實實現不難,就是有點費資源。

      漸漸我,我就忘了這個問題。

      一個偶然

      去年,在改進我制作的一個在某 CMS 平臺運行的圖片壓縮插件的時候,我忘了是從哪里復制過來的一個代碼,讓我這個插件有了這樣一個好功能 : 單擊某個按鈕可以在新的標簽頁預覽一個圖片。至于原程序這里放不下,但我們可以這樣體驗一下,在 F12 瀏覽器 JS 控制臺輸入下面的代碼:

      const imgurl = 'https://assets.cnblogs.com/logo.svg';  // 博客園的 logo 地址
      const imgTempBlob = new Blob(['<img style="max-width:100%" src="'+ imgurl +'">'], {type: 'text/html'});
      const imgBlobObjurl = window.URL.createObjectURL(imgTempBlob);
      window.open(imgBlobObjurl, '_blank');
      URL.revokeObjectURL(imgBlobObjurl);  // 如果不添加這一行,那么那個地址會一直有效,直到瀏覽器自己清除
      

      然后瀏覽器會馬上打開一個新頁面,然后將 博客園 的 logo 給展示了出來!如圖所示:

      image

      我當時被震驚了。

      在過去,我對 js 的二進制的理解只有 ArrayBuffer base64 Blob 三者,且這三者是可以互相轉化的。直到今天,我才知道在 JS 二進制 世界里竟然還有一個 createObjectURL 這樣一個方法。

      createObjectURL 可以把內存里的一個東西,比如一個字符串、一個圖像二進制,等,轉換成一個 URL,這樣你就可以使用 DOM 渲染出來。比如你加載了一張圖片,然后修改了一些內容,接下來要渲染到網頁上,就會用到這個函數方法。

      當然,我們也要注意,每次調用 createObjectURL() 時,都會創建一個新的對象 URL,即使已經為同一個對象創建了一個 URL。當不再需要這些對象時,必須通過調用 URL.revokeObjectURL() 來釋放它們,瀏覽器會在卸載文檔時自動釋放對象 URL;然而,為了優化性能和內存使用,如果在安全時間內可以明確卸載,就應該卸載。createObjectURL() 創建的 URL 會占用內存,如果不手動釋放,可能會導致內存泄漏。

      這個真是好用,而且用在圖片的預覽上真的太恰當了!為什么很少見到有人使用它呢?或者說我幾乎沒在別的地方見過 xxx.com/c533df96-d49e-49af-9a8c-bdbab35b7baf 類似的地址呢?可能是會造成性能上的不妥吧。

      我后來發覺到里面的 HTML 代碼,我感覺它可以再復雜一點。

      它可以不預覽圖片,它可以作為 HTML 在線編輯器的最徹底的預覽!

      預覽 HTML 代碼

      我們可以寫一個簡單的文本框,然后寫一個按鈕,讓按鈕在單擊后,在新的頁面預覽我們的代碼運行效果。代碼如下:

      <textarea id="htmlcode" placeholder="在此輸入 HTML 代碼"></textarea><br>
      <button id="runcode">在新窗口預覽</button>
      
      <script>
      runcode.onclick = function() {
          const codeBlob = new Blob([`<meta charset="utf-8">` + htmlcode.value], {type: 'text/html'});
          const codeTempUrl = window.URL.createObjectURL(codeBlob);
          window.open(codeTempUrl, '_blank');
          URL.revokeObjectURL(codeTempUrl);
      }
      </script>
      

      運行效果如下:

      image

      單擊按鈕后,

      image

      很不錯。然后我們就可以根據我們自身的需要,為其添加這樣的功能!

      • 在寫代碼的時候,添加保存快捷鍵,讓其保存到我們的瀏覽器的 localStorage 里,防止丟失代碼
      • 設置一個保存按鈕
      • 把 CSS 和 JS 也搞里頭,單獨設置兩個框
      • 一鍵清除記錄
      • 簡單的把界面給美化一下
      • 可以將當前的頁面轉化為 HTML 文件下載

      然后我就搞成了這個樣子!

      大家可以單擊這個地址,查看運行效果! https://www.ccgxk.com/528.html 我的站點上的一個頁面將其嵌入其中了。

      image

      我感覺真的很實用。我在使用 Gemini 這種對前端輸出比較厲害的 AI 的時候,它會給我輸出一大堆的 HTML ,有時候還會分 CSS 和 JS 輸出,我使用這個頁面來輔助測試的話還不錯,比類似于 codepen 那種頁面好用很多。

      下面是目前的全部代碼,可能還有很多地方要改進的,我之后在使用過程中會進行迭代,并實時更新到我的站點上的那個頁面上

      <style>
      @keyframes fadeOut {
      from { opacity: 1; }
      to { opacity: 0; }
      }
      
      button { cursor: pointer; }
      
      .code-textarea {width: 100%;height: 250px;padding: 1em;background-color: azure; border: 0; outline: 0;}
      
      #htmlcode::::placeholder { color: grey; }
      
      .code-action-btn {float: right;background-color: antiquewhite;border: 0;width: 60px;height: 50px;font-size: 22px;padding: 0;}
      </style>
      
      <div style="width: 600px;max-width: 100%;">
      	<textarea placeholder="在此處輸入 HTML 代碼,單擊下面的【運行】,瀏覽器會新建一個空白標簽頁運行預覽..." name="code" id="htmlcode" class="code-textarea"></textarea><br>
      	<button class="code-action-btn" id="runhtml">運行</button>
      	<button class="code-action-btn" id="dwnhtml" style="margin-right: 10px;">下載</button>
      	<button class="code-action-btn" id="delhtml" style="margin-right: 10px;">清空</button>
      	<button class="code-action-btn" id="savehtml" style="margin-right: 10px;">保存</button>
      	<details>
      	<summary style="cursor: pointer;background-color: cornsilk;width: fit-content;">CSS + JS
      		<div id="res_info" style=" display: inline; margin-left: 10px; background-color: white; padding-left: 10px; "></div>
      	</summary>
      	CSS <br>
      	<textarea class="code-textarea" name="code" id="csscode"></textarea><br>
      	JS <br>
      	<textarea class="code-textarea" name="code" id="jscode"></textarea>
      	</details>
      </div>
      
      <script>
      // 生成隨機字符串
      function generateRandomString(length = 8) {
          const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
          let result = '';
          for (let i = 0; i < length; i++) {
              result += chars.charAt(Math.floor(Math.random() * chars.length));
          }
          return result;
      }
      
      // 瀏覽器運行后檢測本地 storage
      const codeData = (JSON.parse(localStorage.getItem('codeData'))) || false;
      if (codeData) {
          htmlcode.value = codeData.htmlcode;
          csscode.value = codeData.csscode;
          jscode.value = codeData.jscode;
      }
      
      // 點擊 運行 事件
      runhtml.onclick = function() {
          saveHtmlFunc();
          let testBlob;
          if (csscode.value || jscode.value) {
              testBlob = new Blob([`<meta charset="utf-8">` + `<style>` + csscode.value + `</style>` + htmlcode.value + `<script>` + jscode.value + `</sc` + `ript>`], {
                  type: 'text/html'
              });
          } else {
              testBlob = new Blob([`<meta charset="utf-8">` + htmlcode.value], {
                  type: 'text/html'
              });
          }
          const codeTempUrl = window.URL.createObjectURL(testBlob);
          window.open(codeTempUrl, '_blank');
          URL.revokeObjectURL(codeTempUrl);
      }
      
      // 保存 HTML 函數
      function saveHtmlFunc() {
          const codeContent = {
              htmlcode: htmlcode.value,
              csscode: csscode.value,
              jscode: jscode.value
          };
          localStorage.setItem('codeData', JSON.stringify(codeContent));
          res_info.innerHTML = "<span style='animation: fadeOut 3s forwards; opacity: 1;'>已暫存</span>";
      }
      
      // 按下保存快捷鍵后
      document.addEventListener('keydown', function(e) { // 保存快捷鍵
          if (e.keyCode == 83 && (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey)) {
              e.preventDefault();
              saveHtmlFunc();
          }
      });
      
      // 點擊 下載 事件
      dwnhtml.onclick = function() {
          if (!htmlcode.value) {
              return 0;
          }
          const fileName = generateRandomString() + '.html';
          let testBlob;
          if (csscode.value || jscode.value) {
              testBlob = new Blob([`<meta charset="utf-8">` + `<style>` + csscode.value + `</style>` + htmlcode.value + `<script>` + jscode.value + `</sc` + `ript>`], {
                  type: 'text/html'
              });
          } else {
              testBlob = new Blob([`<meta charset="utf-8">` + htmlcode.value], {
                  type: 'text/html'
              });
          }
          const downloadLink = document.createElement('a');
          downloadLink.href = URL.createObjectURL(testBlob);
          downloadLink.download = fileName;
          document.body.appendChild(downloadLink);
          downloadLink.click();
          document.body.removeChild(downloadLink);
          URL.revokeObjectURL(downloadLink.href);
      }
      
      // 點擊 清空 事件
      delhtml.onclick = function() {
          htmlcode.value = '';
          csscode.value = '';
          jscode.value = '';
          localStorage.removeItem('codeData');
      }
      
      // 點擊 保存 事件
      savehtml.onclick = function() {
          saveHtmlFunc();
      }
      </script>
      
      posted @ 2025-04-17 19:34  獨元殤  閱讀(2116)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 精品一区二区三区不卡| 国产精品无码一区二区三区电影 | 青青草国产自产一区二区| 欧美人成精品网站播放| 久久久久国产一级毛片高清版A| 承德市| 午夜在线欧美蜜桃| 亚洲精品一区二区三区大桥未久| 日本高清一区免费中文视频| 国产精久久一区二区三区| 在线观看美女网站大全免费 | 免费无码无遮挡裸体视频在线观看| 赤壁市| 色欲天天婬色婬香综合网| 国产熟睡乱子伦视频在线播放| 游戏| 国产欧美精品一区二区三区-老狼| 久久久这里只有精品10| 国语精品自产拍在线观看网站| 精品嫩模福利一区二区蜜臀| 国产成人综合色就色综合| 绍兴县| 高级艳妇交换俱乐部小说 | 久久99精品久久久久久9| 成人精品天堂一区二区三区| 国内精品一区二区不卡| 国产av无码国产av毛片| 人妻系列无码专区免费| 人妻熟女一二三区夜夜爱| 日韩大片看一区二区三区| 日本黄韩国色三级三级三| 亚洲成aⅴ人片久青草影院| 日韩美女亚洲性一区二区| 国产亚洲tv在线观看| 中国女人熟毛茸茸A毛片| 精品日韩精品国产另类专区| 激情亚洲内射一区二区三区| 97久久超碰亚洲视觉盛宴| 亚洲国产精品午夜福利| 午夜国产小视频| 人妻系列无码专区无码中出|