此篇會探討為什麼雙括號 Mustache 無法渲染出 HTML tag 的問題
科普 Mustache
- 使用方式:
{{ }} 雙括號
- 用途:動態顯示 data 以及綁定
支持兩種參數
Inside text interpolations 文本插值
- 最基本的數據綁定方式
1
<span>Message: {{ msg }}</span>
expression 表達式
- 皆會轉換成 JavaScript expressions
1
2
3
4{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div :id="`list-${id}`"></div>
補充:vue templates 中可以使用 JavaScript expressions 的兩種時機
- Inside text interpolations 使用
{{}} mustaches
- 任何使用
v-
開頭的屬性值(例如:v-if、v-bind)
以上屬於對 Mustache 的介紹,下方開始探討為什麼無法渲染出 HTML tag。
問題探討
Q:為什麼無法渲染出 HTML tag
A:官方文件中有提到「mustaches interpret the data as plain text」
代表 mustaches 渲染得結果都會作為純文字(string)渲染到畫面上,因此不會解析成 HTML tag。
- 文件中也有表示可以透過 Raw HTML(v-html) 來渲染出 HTML tag。
下方示範如何解決
解決方法
情境範例:依照 product.is_enabled 渲染出不同的 class、textContent
錯誤範例:因為渲染出來的是純文字,不會解析成 HTML tag。
1 | {{ product.is_enabled ? '<span class="text-success">啟用</span>' : '<span>未啟用</span>' }} |
因此如果渲染 HTML 需求,不能透過 Mustache 字串插值的方式,下方示範演示其他兩種解決方法。
三元運算子
- 相同類型的結構可以使用
三元運算子
動態切換不同的值,這邊 class 綁定的值屬於陣列
。
1 | <span :class="[product.is_enabled ? 'text-success' : 'text-warning']">{{ product.is_enabled ? '啟用' : '未啟用' }}</span> |
- 如果動態切換條件只需要判斷一種結果,則下方範例兩種形式都可以。
1 | <span :class="{'text-success': product.is_enabled, 'text-warning': !product.is_enabled}">{{ product.is_enabled ? '啟用' : '未啟用' }}</span> |
v-html
- 透過三元運算子來決定要渲染的 HTML tag。
1 | <div v-html="product.is_enabled ? `<span class='text-success'>啟用</span>` : `<span class='text-warning'>未啟用</span>`"></div> |
- data 定義一個變數來存放 html tag,再作為 v-html 綁定對象。
1 | const app = { |
提醒:這種動態渲染 HTML 方式,容易導致 XSS 漏洞,因此必須要在可信任的 content(例如上方範例的 rawHtmlEnabledIsTrue、rawHtmlEnabledIsFalse)中在使用 v-html,絕對不能用在使用者提供的內容上(例如:input)。
延伸問題