1. 程式人生 > >讓 innerHTML 進來的 script 程式碼跑起來

讓 innerHTML 進來的 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>

參考:

相關推薦

innerHTML 進來script 程式碼起來

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

我們的LED燈起來

基礎 images ges 結合 log 基本上 很多 出了 網上    相信我們通過前面兩章的討論我們基本上對51單片機的代碼編寫有了一定初步的了解了,所以我們如果還是有很多不懂得的地方我們一定得結合圖片,或者去網上查找一些相關的資料,一定得讓不懂得的地方徹底弄懂,不要讓

Mongo在Spring中起來

-s sts find wired repos Java實體類 remove criteria sprint 本文標題為《讓Mongo在Spring中跑起來》,旨在Spring中如何成功連接MongoDB並對其進行增刪改查等操作,由於筆者也是剛接觸,對其中的一些原由也不

Project PerfectSwift在伺服器端起來-Hi Linux(二)

編者語:就這樣就過完年了,話說大家開始回到各自的工作單位上,感覺還不錯吧。開篇寫了一個簡單的入門,今天想說說怎麼讓Perfect專案在Linux上執行。                 Swift開源

innerHTML的js指令碼執行起來 總結

網上搜集的一些方法: 1、IE中插入的HTML裡,<script>前面有其他物件,並且script 設定了 defer ;  firefox 把物件重新 append 或者 insertBefore 一次 var fillHTML = function (el,HTMLString) {    

corethink功能模塊探索開發(四)這個模塊起來

src 後臺菜單 evel pst 新建 mod depend htm news 讓這個模塊跑起來,太費勁了,多半原因是自己太粗心,opencmf.php中“uid”寫成了“pid”,de了好幾天的bug也沒有搞出來,又加上最近發生了些事(brokenhearted)。。。

Kafka在scala裏面起來

時間 all tex 區分 系統變量 factor 命名 zoo.cfg topic Kafka集群對消息的保存是根據Topic進行歸類的,由消息生產者(Producer)和消息消費者(Consumer)組成,另外,每一個Server稱為一個Broker(經紀人)。對於Ka

Web應用起來

集成 不能 需要 host 部署 pos http version cnblogs 上一篇我們在基於Maven構建的Java Web項目中編寫了Servlet以及jsp:http://www.cnblogs.com/lay2017/p/8468519.html 本文,我們將

Qt桌面圖示起來

效果如下: 實現要關注以下幾點 WindowsAPI——如何獲取桌面圖示個數 WindowsAPI——如何獲取桌面解析度 WindowsAPI——如何設定每個圖示的位置 WindowsAP

怎樣Nordic的nrf52840起來第一個例程

"·····user Guide v1.2”進行開發環境的搭建。 然後,用usb2.0線,連線development kit和PC,開啟nRF官方推出的nRFgo studio,此時可以在左側欄,看到一個裝置: 然後點選該裝置,,右側出現頁面 圖中右

如何在idea中部署一個tomcat伺服器,web專案起來

1. 需求: 在idea上面部署一個tomcat伺服器,讓web專案跑起來,新建一個tomcatDome,來使歡迎頁面展示。 2.新建一個dome 頁面程式碼 3.在idea上設定部署tomca

如何我們的PHP在Jexus中起來

最近一段時間,經常看到不少的朋友在問,應該怎麼設定才能夠讓Jexus支援PHP。其實,Jexus在很早之前就已經是可以支援PHP,像Apache或Nginx一樣充當PHP的Web伺服器的。不過由於沒有這個方面的需求,我也一直沒有用它這一項功能。 早在前兩天,群裡一名朋友找到我,他想把一個PHP版的BBS改為

10大最適合程式設計的字型推薦下載,程式碼起來更美更舒服!

現在有事沒事就喜歡寫寫程式碼的人越來越多了,對於成天盯著螢幕工作的開發人員來說,程式設計程式碼可能是每天見得最多的東西了。可是絕大部分人都一直使用編輯器預設的字型,其實,換一套適合自己的程式設計字型不僅能讓程式碼看得更舒服,甚至還能提高工作效率的!         如果你有

初學者把Rxjava+Retrofit先起來

這是一篇淺顯的Rxjava+Retrofit文章,從初學者出發,感覺如果工作中沒有充足發揮自學技能的專案,直接去看大佬們寫的很深入的講解,特別容易遺忘、懵甚至不理解,所以我決定寫一篇淺顯的使用Rxjava+Retrofit的文章。所需依賴庫:compile"io.reacti

程式碼起來更舒服(1):選擇適合的配色方案(更新配色方案生成器)

“讓程式碼看起來更舒服”,看到這個標題,也許你會條件反射地以為我要講“重構”或者“編碼規範”等等。噢,可愛的開發人員,我們暫且不談技術,只談體驗。讓我們來裝扮一下每天都要面對的Visual Studio,讓程式碼看起來更舒服。 下圖展示了Visual Studio 2008預設的編輯器,為了讓程式碼更加容易

cocos2dx開發-例子(新建cocos專案)在android機器上起來

新建Cocos專案 解壓原始碼得到資料夾cocos2d-x-3.2alpha0 進入目錄cocos2d-x-3.2alpha0\tools\cocos2d-console\bin執行 python cocos.py new BuckGameCC -p com.cocos2

玩轉Eclipse — 程式碼起來

        “工欲善其事,必先利其器”。好的工具,能夠使工作事半功倍;充分發揮工具的優勢,更能錦上添花。Java一直穩居TIOBE程式語言排行榜的前兩名,而Eclipse是Java程式設計師的首選開發環境,其應用的普遍程度可想而知。在以前看過的一篇博文中瞭解到,大牛都喜

create-react-app原始碼解析(一),npm run start如何專案起來

    小編花了點時間,大致弄懂npm run start如何執行專案的原理了,現在給大家分享下心得!npm run start是通過node跑js檔案,從而專案得以執行,小編通過npm run eject拿到了所有配置,然後通過解析原始碼,明白瞭如果通過webpack等讓專

一個javaweb新手,eclipse如何配置tomcat,純前端頁面在瀏覽器起來

ZZ本是一個前端,大學時期是軟體工程專業,但是上課沒有好好聽課,後來就變成了一個前端。。。現在想學起javaweb,對於java的東西真的是一點都不會了,於是求助書本與學長,成功讓我寫好的前端頁面在自己搭的環境下跑起來了,感謝學長*v*~~~ 接下來是步驟: 需要軟體那些

angular2部署到tomcat中,起來

首先使用構建命令(npm run build或ng build)打包,打包完成後專案中會出現一個dist的目錄,這個目錄就是我們最終要部署的包了,把它命名為cc-client(關於打包後的base路徑修改,參考後面的備 注)就可以了。 將命名好的cc-client整個目錄複製到tomcat的webapps