讓 innerHTML 進來的 script 代碼跑起來

来源:http://www.cnblogs.com/zichi/archive/2016/03/17/run-innerHTML-script.html
-Advertisement-
Play Games

今天來簡單聊聊如何讓 innerHTML 進來的 scrip 代碼跑起來的問題。 前臺請求一個介面,介面返回一些 HTML 標簽拼接成的字元串,以供前端直接 innerHTML 生成 DOM 元素,這樣的做法非常普遍。但是你是否遇到過,如果字元串中拼接的 HTML 標簽中有 script 標簽,那麼


今天來簡單聊聊如何讓 innerHTML 進來的 scrip 代碼跑起來的問題。

前臺請求一個介面,介面返回一些 HTML 標簽拼接成的字元串,以供前端直接 innerHTML 生成 DOM 元素,這樣的做法非常普遍。但是你是否遇到過,如果字元串中拼接的 HTML 標簽中有 script 標簽,那麼該段腳本是無法執行的,這並不是 bug,而是 w3c 的文檔規定的。

比如如下這段代碼,innerHTML 插入的腳本(alert)並不會執行:

<div id="myDiv">
</div>

<script>
  // 模擬介面返回數據
  var strVar = "";
    strVar += "<script>alert('hello world')<\/script>";

  document.getElementById('myDiv').innerHTML = strVar;
</script>

那麼問題來了,如何使得 innerHTML 進來的 script 代碼能夠跑起來?

方案一:重新構造 script 標簽

思路非常簡單,構造新的 script 標簽,然後該標簽的 innerHTML 賦值為需要渲染的腳本。偽代碼如下:

var s = document.createElement('script');
s.innerHTML = text;
document.body.appendChild(s);

當然如果要寫的完美一點,執行完 s 後還需要 remove 掉。如何獲取 text 值?兩個方法,其一可以正則匹配 strVal,提取 script 標簽內的內容,這點和 BigRender 類似,而 BigRender 除了提取 script 標簽,還需要提取 style 標簽,無疑更複雜;第二個方法是可以用 document.getElementsByTagName('script') 獲取插入 DOM 但並未執行的 script 腳本,但是這樣會把頁面所有腳本全部提取,所以還需要判斷。(可以獲取某一節點下的 script 標簽)

如果是外部的 js 文件,需要為新建的 script 元素添加 src 屬性即可。

方案二:eval 大法

事實上,如果是 inline JavaScript,方案一求得的 text,可以直接 eval 之。

但是如果是外聯 js 文件,同上,需要新建 script 標簽然後指定 src 屬性。

方案三:document.write

document.write 接收一個字元串作為參數,並且支持 script 標簽以及其他 HTML 標簽拼成的字元串,看起來似乎是完美的方案。不過鑒於 document.write 的怪屬性,只適合 strVal 在首頁輸出流中的渲染情況,如果是非同步的請求,就可以放棄了。

舉個慄子:

hello world
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<div>
<script>
    $.get('data.php', function(data) {
      document.write(data);
    })
</script>
</div>

目的似乎是為了在 div 中嵌入 data,但是 hello world 字樣也消失了,很顯然,非同步請求後重啟輸入流,將頁面全部覆蓋掉了。

方案四:jQuery html() 方法

使用封裝過的方法無疑是個好辦法:

<div id="myDiv"></div>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
  $.get('data.php', function(data) {
    $('#myDiv').html(data);
  })
</script>

如果已經引入了 jQuery,無疑是最佳方案,沒必要重覆造輪子了。

方案五: 利用 img 標簽

黑魔法,如果後臺介面可控的話。

比方說我希望 innerHTML 的內容如下:

<div></div>
<script>
  alert('hello world');
</script>

我們可以這樣構造 img:

<div id='myDiv'></div>
<script>
  var str = "<div></div>";
  str += "<img src='empty.gif' onload='alert(\"hello world\"); this.parentNode.removeChild(this);' />";
  document.getElementById('myDiv').innerHTML = str;
</script>

其他: 特殊的 IE

事實上,一定條件下,innerHTML 進來的 script 腳本,在 IE(IE9-?)下是可以觸發的。

需要滿足的條件如下:

  • 腳本有 defer 屬性
  • 腳本並不是 innerHTML 的第一個元素( script 元素必須位於 "有作用域的元素" 之後。如果通過innerHTML 插入的字元串開頭就是一個 "無作用域的元素",那麼 IE 會在解析這個字元串前先刪除該元素)

code:

<body> 
<div id='myDiv'></div>
<script type="text/javascript">
  var strVar = "";
  strVar += "<span style='display: none'>hack ie</span><script defer='true'>";
  strVar += "alert('hello world');";
  strVar += "<\/script>";

  document.getElementById("myDiv").innerHTML = strVar;
</script>
</body>

參考:


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 大家先看一段簡單的jquery ajax 返回值的js 代碼 function getReturnAjax{ $.ajax({ type:"POST", http://www.cnblogs.com/wlmemail/admin/%22ajax/userexist.aspx", data:"user
  • JS and Jquery 都能獲取頁面元素的寬度,高度和相對位移等數值,那他們之間能相互轉換或替代嗎,寫法又有哪些差異呢?本文將詳細為你介紹。 1.Js獲取瀏覽器高度和寬度document.documentElement.clientWidth ==> 瀏覽器可見區域寬度 document.doc
  • 瀏覽器可以被認為是使用最廣泛的軟體,本文將介紹瀏覽器的工作原理,我們將看到,從你在地址欄輸入google.com到你看到google主頁過程中都發生了什麼。 將討論的瀏覽器 今天,有五種主流瀏覽器——IE、Firefox、Safari、Chrome及Opera。 本文將基於一些開源瀏覽器的例子——F
  • 試玩:http://hovertree.com/game/9/ 貪吃蛇是一種風靡全球的小游戲,就是一條小蛇,不停地在屏幕上游走,吃各個方向出現的蛋,越吃越長。只要蛇頭碰到屏幕四周,或者碰到自己的身子,小蛇就立即斃命。和別的游戲不同,貪食蛇是一個悲劇性的游戲。許多電子游戲都是打通關到底,游戲操作者以勝
  • 一個web前端的小白,聽前輩說寫好筆記很關鍵,so 特此用博客來開始記錄自己的旅程——Web之路 最近幾天看的HTML 1、糾正一個認知錯誤 “HTML是一種編程語言” ————(錯) HTML (全名:Hype Text Mark-up Language ) 超文本標記語言 ,它是一種描述性標記語
  • 模塊化:每個模塊只完成一個獨立的功能,然後提供該功能的介面。模塊間通過介面訪問。模塊中的(過程和數據)對於其它模塊來說是私有的(不能訪問修改) 原始人寫法: 這種寫法已經有點模塊的樣子了,一下就能看出這幾個函數和變數之間的聯繫。 缺點在於所有變數都必須聲明為公有,所以都要加this指示作用域以引用這
  • 現代web頁面里到處都是ajax,所以處理好非同步的代碼非常重要。 這次我重新選了個適合展示非同步處理的應用場景——搜索新聞列表。由於有現成的介面,我們就不用自己搭服務了。 我在網上隨便搜到了一個新聞服務介面,支持jsonp,就用它吧。 一開始,咱們仍然按照action->reducer->compon
  • 前些天,我朋友發了這個段CSS我。 Q:color是哪個? A: 000 不是麽? what the fuck !! 結果是 fff。作為一個頁面仔我表示。。。 經過修行,我弄得了它們的規矩。 在一大堆css規則中,到底哪個有效。這其實由這3個說的算 特殊性(權重)、重要性、繼承。 特殊性 簡單的說
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...