Explain Codes LogoExplain Codes Logo

Display unescaped HTML in Vue.js

javascript
prompt-engineering
best-practices
security
Alex KataevbyAlex Kataev·Jan 24, 2025
TLDR

Inject HTML content directly into your Vue.js templates utilizing the v-html directive.

<div v-html="yourHtmlContent"></div>

Supply yourHtmlContent in your data:

data() { return { yourHtmlContent: '<span style="color: red;">Important</span> message' }; }

Note: Reserve v-html for verified safe content to prevent XSS attacks.

Use v-html, but wisely

The v-html directive might seem too good to be true and, indeed, it requires precise handling. Always sanitize the content plugged into v-html to maintain your app's breath of fresh code. For dynamic content, consider incorporating a computed property or a function for this task.

A helping computed property
computed: { cleanHtml() { // Remember! Sanitize before you serve return this.sanitizeHtml(this.yourHtmlContent); } }
A method to the madness
methods: { sanitizeHtml(html) { // Lather, rinse and repeat with DOMPurify, or your sanitizer of choice return DOMPurify.sanitize(html); } }

Looming threat of XSS attacks will make you think twice before dealing with user-provided content, hence always rely on accredited libraries for content sanitization. DOMPurify gets the job done!

Visualization

Imagine an art gallery. But, here's the twist:

🎨 In Vue.js, by default, HTML tags are shrouded; a masterpiece hidden behind a veil (escaped).

Lift the veil, behold the beauty (display unescaped HTML):

<div v-html="rawHtmlContent"></div> // Parting the red sea of tags, one v-html at a time

The transformation:

Before: [🖼️🎭] // It's there but you can't see it After: [🖼️] // Voila! True colors shining through

Remember: Security matters. Unveil the content only when you're certain of its sanctity.

Think before using v-html

v-html might be tempting but ponder upon alternatives before you plunge. A more secure approach is often right around the corner - a typical expression interpolation {{ }} or slots could be just what you're looking for.

The simpler, the safer
<span>{{safeText}}</span> // A simple, but effective deterrence
Supercharged with slots
<template v-slot:default> <span>Slot content here</span> // Slots: snug as a bug in a Vue rug </template>

v-html: The frenemy of compatibility

v-html might not get along with <template> or Vue's <transition> elements, causing skirmishes in the DOM battlefield. Stick with the good old <div> and <span> when rendering unescaped HTML. Remember, v-html content isn't reactive with children mutations, meaning Vue won’t keep an eye on DOM alterations made to v-html rendered content.

Where reactivity fades
😉 Vue’s like a watchful guardian, but doesn’t keep tabs on `v-html` rendered content.

Understanding v-html better

v-html might appear plain sailing, but it can make your code more complex to maintain and debug. It's a magic trick where content mysteriously appears, puzzling developers during maintenance.