0%

Vue 雙括號 Mustache 無法渲染出 HTML tag

此篇會探討為什麼雙括號 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
2
<span :class="{'text-success': product.is_enabled, 'text-warning': !product.is_enabled}">{{ product.is_enabled ? '啟用' : '未啟用' }}</span>
<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
2
3
4
5
6
7
8
9
const app = {
data() {
return {
rawHtmlEnabledIsTrue: "<span class="text-success" v-if="product.is_enabled">啟用</span>",
rawHtmlEnabledIsFalse: "<span class="text-warning" v-if="!product.is_enabled">未啟用</span>"
}
}
}
<div v-html="product.is_enabled ? rawHtmlEnabledIsTrue : rawHtmlEnabledIsFalse"></div>

提醒:這種動態渲染 HTML 方式,容易導致 XSS 漏洞,因此必須要在可信任的 content(例如上方範例的 rawHtmlEnabledIsTrue、rawHtmlEnabledIsFalse)中在使用 v-html,絕對不能用在使用者提供的內容上(例如:input)。

延伸問題