假設我們有一段文字:
要使用 Vue 將其顯示非常的容易:
輸出結果:
咦? 等等,不對耶,換行呢?
原來 v-text 會將內容放到節點的 textContent 屬性中,並不會將內容解析為 HTML,所以不會換行,其實要顯示換行非常簡單:
就是使用 <template> ,在裡面使用 v-for 將文字片段拆分為單行,在後面加入 <br/> 區塊
上面的程式碼有個小小的問題,就是最後一行後面會有個空白行,不過要解決也十分簡單:
當然!可以使用 Vue 的自定義指令(Custom Directives),只要加上 v-insert-linebreak 這個自定義指令,就可以在 Vue3 被掛載和更新時自動將換行符號替換為 <br/> 了!
註:本文示範的 Custom Directives 是使用 Vue3 的寫法:
漂亮,以後只要使用 v-insert-linebreak 就可以解決問題了,但,好像有程式碼重複了,未來要更改一次要改兩個位子的程式碼,能不能復用呢?
當然:
還有什麼其他方式呢?觀迎留言
參考資料:
mdn - Node.textContent
Vue.js - Built-in Directives
Vue.js - Custom Directives
const str = `這是第一行
這是第二行
這是第三行`
要使用 Vue 將其顯示非常的容易:
<div >
{{ str }}
</div>
輸出結果:
這是第一行 這是第二行 這是第三行
咦? 等等,不對耶,換行呢?
原來 v-text 會將內容放到節點的 textContent 屬性中,並不會將內容解析為 HTML,所以不會換行,其實要顯示換行非常簡單:
方法一: v-html
將每行資料加上 <br/>,使用 v-html 能夠直接將原始資料顯示出來(放到 innerHTML 屬性中,會解析 HTML)。但是這種做法很可能會受到「跨站腳本攻擊(Cross-Site Scripting, XSS)」,因此不應該被使用,不過這確實也是一種方法。
const str = `這是第一行<br/>
這是第二行<br/>
這是第三行`
<div v-html="str">
</div>
方法二: 使用 CSS 的 white-space
white-space 有兩個屬性可以使用:- pre-line: 合併連續空白符號,但保留換行
- break-spaces: 合併連續空白符號,但保留換行和其他空白符號
<div style="white-space: pre-line;">
{{ str }}
</div>
方法三: 在 template 上執行 v-for 拆分內容和換行
有些時候不能使用 css (例如要將頁面輸出為其他格式時),那難道就只能使用 v-html 了嗎? 其實我們可以自己換行。就是使用 <template> ,在裡面使用 v-for 將文字片段拆分為單行,在後面加入 <br/> 區塊
<template v-for="(line, index) in str.split('\n')" :key="index">
{{ line }}<br/>
</template>
上面的程式碼有個小小的問題,就是最後一行後面會有個空白行,不過要解決也十分簡單:
<template v-for="(line, index) in str.split('\n')" :key="index">
{{ line }}<br v-if="index !== str.split('\n').length - 1"/>
</template>
方法四: 使用 Vue 中的自定義指令
上面的方法會不會太簡單了,而且每次都要手動換很麻煩,有沒有厲害一點的方式?當然!可以使用 Vue 的自定義指令(Custom Directives),只要加上 v-insert-linebreak 這個自定義指令,就可以在 Vue3 被掛載和更新時自動將換行符號替換為 <br/> 了!
註:本文示範的 Custom Directives 是使用 Vue3 的寫法:
const insertLinebreak = {
mounted: (el) => {
el.innerHTML = el.innerHTML.replace(/\n/g, '<br/>')
}
updated: (el) => {
el.innerHTML = el.innerHTML.replace(/\n/g, '<br/>')
},
}
export default {
data() {
return {
str: `這是第一行
這是第二行
這是第三行`
}
},
directives: {
insertLinebreak,
}
}
<div v-text="str" v-insert-linebreak>
</div>
漂亮,以後只要使用 v-insert-linebreak 就可以解決問題了,但,好像有程式碼重複了,未來要更改一次要改兩個位子的程式碼,能不能復用呢?
當然:
const insertLinebreak = {
mounted: (el) => {
insertLinebreak.updated(el);
},
updated: (el) => {
el.innerHTML = el.innerHTML.replace(/\n/g, '<br/>')
},
}
完美!
還有什麼其他方式呢?觀迎留言
參考資料:
mdn - Node.textContent
Vue.js - Built-in Directives
Vue.js - Custom Directives
留言
張貼留言
如果有任何問題、建議、想說的話或文章題目推薦,都歡迎留言或來信: a@ruyut.com