HTML 標(biāo)簽顯示在頁面上的Bug:標(biāo)簽的轉(zhuǎn)義及反轉(zhuǎn)義

問題背景

項(xiàng)目開發(fā)中,本想把從后臺(tái)獲取到的 meaningVaule 值填充到頁面上捅厂,結(jié)果 html 標(biāo)簽并沒有被處理掉,而是顯示在頁面上了焙贷。如圖所示,html 標(biāo)簽顯示在了瀏覽器中贿堰。

p 標(biāo)簽顯示出來了!

下圖展示的是從后臺(tái)獲取的數(shù)據(jù),含有meaningValue字段:

json 數(shù)據(jù)

問題分析

現(xiàn)在想要的目標(biāo)是:html 標(biāo)簽不要顯示出來庶灿,而是應(yīng)該去規(guī)范 html 文檔的顯示效果,比如遇見<p>標(biāo)簽則另起一個(gè)段落往踢。

而實(shí)際上呢,瀏覽器端在進(jìn)行DOM渲染時(shí)峻呕,把形如&lt;&gt;這樣的字符串趣效,解析成了<>英支,繼而把&lt;p&gt; 解析為<p>這樣的HTML標(biāo)簽。然后就直接把解析后的字符串直接顯示在了頁面中干花,不再進(jìn)行 html標(biāo)簽語義分析。由此可以看出池凄,瀏覽器端自己轉(zhuǎn)義了 轉(zhuǎn)移字符抡驼,這樣的好處很明顯肿仑,可以有效的避免代碼注入攻擊,提升網(wǎng)站的安全原因尤慰。

如此分析一番后,解決的方案也就水落石出了:在瀏覽器DOM渲染前伟端,先把形如&lt;&gt;這樣的字符串解析成<责蝠、>党巾,再把解析后的新的字符串(形如<p>感知和體驗(yàn)...</p>)進(jìn)行DOM渲染操作霜医,即可在終端頁面上渲染出最終與其的結(jié)果。

正確的渲染結(jié)果如下圖所示:

p 標(biāo)簽被正確的渲染出來

解決方案代碼

所謂HTML編碼肴敛,其實(shí)就是將字符轉(zhuǎn)換為HTML實(shí)體,這是防止腳本注入攻擊的重要手段之一。

下面的代碼中給出了通用的轉(zhuǎn)義與反轉(zhuǎn)義含有HTML標(biāo)簽的字符串的方法巩搏。

/**
 * 把轉(zhuǎn)義后的字符串反轉(zhuǎn)義成含有 html 標(biāo)簽的字符串昨登。
 * 示例:
 *      HTMLDecode("&lt;p&gt;什么是3D打印丰辣?");  // "<p>什么是3D打尤銮俊笙什?"
 * @param text
 */
const HTMLDecode = text => {
    let tmp = document.createElement('div');
    tmp.innerHTML = text;
    const output = tmp.innerText || tmp.textContent;
    tmp = null;
    return output;
}

/**
 * 轉(zhuǎn)義含有 html 標(biāo)簽的字符串。
 * 示例:
 *      HTMLEncode("<p>什么是3D打铀銎尽?");   // "&lt;p&gt;什么是3D打油城?"
 * @param html
 */
const HTMLEncode = html => {
    let tmp = document.createElement('div');
    (tmp.textContent != null) ? (tmp.textContent = html) : (tmp.innerText = html);
    const output = tmp.innerHTML;
    tmp = null;
    return output;
}

對(duì)于本篇文章開頭的問題愁憔,在渲染meaningVaule字符串前腕扶,調(diào)用一下HTMLDecode方法即可,如下:

const destStr = HTMLEncode(data.meaningValue);
// 再把`destStr`渲染到 DOM 中...

解讀 innerHTML吨掌、innerText、textContent

innerHTML

由于innerTexttextContent均為對(duì)innerHTML內(nèi)容作不同的處理而成膜宋,因此我們需要先明確innerHTML屬性的特點(diǎn)。

賦值操作

賦值操作秋茫,即先對(duì)值的內(nèi)容進(jìn)行模式匹配棉磨,然后把處理后的值賦予給innerHTML屬性学辱。模式匹配結(jié)果將導(dǎo)致 保留將字符轉(zhuǎn)換為HTML實(shí)體 兩個(gè)操作。

一. 以下情況將被保留:

  1. HTML實(shí)體(ASCII實(shí)體策泣、符號(hào)實(shí)體和字符實(shí)體)的實(shí)體名或?qū)嶓w編號(hào);
  2. 符號(hào)實(shí)體和字符實(shí)體對(duì)應(yīng)的字符萨咕;
  3. 沒有HTML實(shí)體與之對(duì)應(yīng)的字符;
  4. HTML標(biāo)簽。(如<img>)聪建。

二. 以下情況將會(huì)執(zhí)行字符轉(zhuǎn)換為HTML實(shí)體:

  1. ASCII實(shí)體對(duì)應(yīng)的字符(<、>金麸、&、'和")挥下。

也就是說除了單獨(dú)的 <揍魂、>棚瘟、&、'和" 會(huì)被轉(zhuǎn)換為實(shí)體名外偎蘸,將原封不動(dòng)地將值賦予給innerHTML屬性。

取值操作

取值操作迷雪,即直接獲取innerHTML屬性值限书。

innerText & textContent

由于innerText并非 W3C 標(biāo)準(zhǔn)屬性振乏,尤其是FireFox 45 之前的版本不支持innerText方法。因此一般情況下可以使用textContent來代替慧邮,但它兩者是否就能完全等同呢?實(shí)際并非如此误澳!

區(qū)別:取值時(shí) innerText會(huì)把只會(huì)獲取節(jié)點(diǎn)里面的文本信息耻矮,而innerHTML 會(huì)獲取節(jié)點(diǎn)下面的所有標(biāo)簽忆谓。innerHTML是符合W3C標(biāo)準(zhǔn)的屬性,而innerText只適用于IE瀏覽器倡缠,因此,盡可能地去使用innerHTML昙沦,而少用innerText
IE中的innerText是需要對(duì)innerHTML的值進(jìn)行:

  1. HTML轉(zhuǎn)義(等同于XML轉(zhuǎn)義,對(duì)<盾饮、&等轉(zhuǎn)義字符進(jìn)行處理)采桃;
  2. 經(jīng)過HTML解釋和CSS樣式解釋;
  3. 之后又剔除格式信息之后留下的純文本普办。

而FF中的textContent沒有2、3步衔蹲,在經(jīng)過了HTML轉(zhuǎn)義之后直接剔除所有html標(biāo)簽后得到的純文本肢娘。

總結(jié):

一言以蔽之踪危,這一部分主要涉及到瀏覽器的兼容性問題猪落。主要思路有以下兩個(gè):

  1. 可以采用上面給出的 HTMLDecode()HTMLDecode()方法贞远,來進(jìn)行 html 標(biāo)簽的轉(zhuǎn)義與還原處理笨忌。
  2. 或者,采用 jQuery 中的方法官疲,來抹平掉不同瀏覽器之間的差異性。

可以參考一下:MDN 之 Node.textContent

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末途凫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子维费,更是在濱河造成了極大的恐慌果元,老刑警劉巖犀盟,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異阅畴,居然都是意外死亡倡怎,警方通過查閱死者的電腦和手機(jī)贱枣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纽哥,“玉大人,你說我怎么就攤上這事昵仅±勰В” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵垦写,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我彰触,道長(zhǎng),這世上最難降的妖魔是什么况毅? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮尔许,結(jié)果婚禮上么鹤,老公的妹妹穿的比我還像新娘味廊。我一直安慰自己,他們只是感情好余佛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著辉巡,像睡著了一般恨憎。 火紅的嫁衣襯著肌膚如雪郊楣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天痢甘,我揣著相機(jī)與錄音,去河邊找鬼塞栅。 笑死者铜,一個(gè)胖子當(dāng)著我的面吹牛放椰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播砾医,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼如蚜!你這毒婦竟也來了压恒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤探赫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后伦吠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡毛仪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了箱靴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腺逛。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡屉来,死狀恐怖路翻,靈堂內(nèi)的尸體忽然破棺而出狈癞,到底是詐尸還是另有隱情茂契,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布掉冶,位于F島的核電站,受9級(jí)特大地震影響厌小,放射性物質(zhì)發(fā)生泄漏恢共。R本人自食惡果不足惜璧亚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望癣蟋。 院中可真熱鬧透硝,春花似錦疯搅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至觉义,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谁撼,已是汗流浹背歧胁。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國打工厉碟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人箍鼓。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像款咖,于是被迫代替她去往敵國和親何暮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子铐殃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • HTML標(biāo)簽解釋大全 一、HTML標(biāo)記 標(biāo)簽:!DOCTYPE 說明:指定了 HTML 文檔遵循的文檔類型定義(D...
    米塔塔閱讀 3,240評(píng)論 1 41
  • 個(gè)人博客:https://yeaseonzhang.github.io 花了半個(gè)多月的時(shí)間富腊,終于又把“JS紅寶書”...
    Yeaseon閱讀 11,524評(píng)論 9 52
  • 前一陣做活動(dòng)有一個(gè)分享文案總是分享錯(cuò)誤,排除法之后發(fā)現(xiàn)是一個(gè)字符的編解碼問題赘被。好幾次遇到這種問題都是懵過去的,這次...
    lzxxx閱讀 700評(píng)論 1 1
  • 有一棵大樹媽媽 這已經(jīng)是她在人間的第90個(gè)年頭了 她一生中生下了許許多多的孩子 就是那一片片濃密的葉子 最后生下來...
    榮生實(shí)驗(yàn)室閱讀 329評(píng)論 0 2
  • PS:因?yàn)檫@是事后總結(jié)民假,具體的錯(cuò)誤當(dāng)時(shí)沒有記錄,有可能錯(cuò)誤與解決方法不匹配羊异。 bad response Forbi...
    學(xué)習(xí)無底閱讀 2,684評(píng)論 1 3