---
title: Vue.js v-text Directive
description: Learn how to use the v-text directive in Vue.js to render text content in the DOM. Understand when to use v-text vs. text interpolation and explore practical examples.
---
Vue.js v-text Directive
Introduction
In Vue.js, the v-text
directive is a built-in feature that allows you to update the text content of an element. It's one of the fundamental directives in Vue that helps manipulate the DOM based on your application data.
The v-text
directive binds the element's textContent
property to the provided expression's value. When the bound data changes, Vue automatically updates the element's text content. This makes it a powerful tool for dynamic content rendering in your Vue applications.
Basic Syntax
The v-text
directive follows a straightforward syntax:
<element v-text="expression"></element>
Where:
element
is any valid HTML elementexpression
is any valid JavaScript expression that evaluates to a string
v-text vs. Text Interpolation (Mustache Syntax)
Before diving deeper, it's worth comparing v-text
with Vue's text interpolation syntax (using double curly braces, often called "mustache" syntax):
<!-- Using v-text -->
<span v-text="message"></span>
<!-- Using interpolation (mustache) -->
<span>{{ message }}</span>
Both approaches achieve the same result but have subtle differences:
-
Content Replacement:
v-text
completely replaces the element's content- Mustache syntax can be used inline with other text
-
HTML Rendering:
- Both
v-text
and mustache syntax escape HTML content, preventing XSS attacks
- Both
-
Flash of Uncompiled Content:
- With mustache syntax, users might briefly see the raw
{{ message }}
before Vue compiles it v-text
doesn't have this issue as it's a directive that Vue processes before rendering
- With mustache syntax, users might briefly see the raw
Basic Examples
Example 1: Simple Text Binding
Let's start with a simple example:
<template>
<div>
<h2 v-text="title"></h2>
<p v-text="content"></p>
</div>
</template>
<script>
export default {
data() {
return {
title: 'Learning Vue.js Directives',
content: 'The v-text directive is used to update element text content.'
}
}
}
</script>
Result:
<div>
<h2>Learning Vue.js Directives</h2>
<p>The v-text directive is used to update element text content.</p>
</div>
Example 2: Dynamic Updates
One of the strengths of Vue.js is reactivity. When the bound data changes, the view automatically updates:
<template>
<div>
<p v-text="counter"></p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
export default {
data() {
return {
counter: 0
}
},
methods: {
increment() {
this.counter++
}
}
}
</script>
In this example, every time you click the button, the counter value increases and the text updates automatically.
Example 3: Using JavaScript Expressions
You can use any valid JavaScript expression with v-text
:
<template>
<div>
<p v-text="'Current time: ' + new Date().toLocaleTimeString()"></p>
<p v-text="firstName + ' ' + lastName"></p>
<p v-text="isActive ? 'Active' : 'Inactive'"></p>
</div>
</template>
<script>
export default {
data() {
return {
firstName: 'John',
lastName: 'Doe',
isActive: true
}
}
}
</script>
Common Use Cases
1. Form Input Feedback
The v-text
directive is useful for displaying validation messages or form feedback:
<template>
<div>
<input
type="text"
v-model="username"
placeholder="Enter username"
/>
<p
v-text="usernameValidationMessage"
:class="{ error: !isUsernameValid, success: isUsernameValid && username }"
></p>
</div>
</template>
<script>
export default {
data() {
return {
username: ''
}
},
computed: {
isUsernameValid() {
return this.username.length >= 3
},
usernameValidationMessage() {
if (!this.username) return 'Username is required'
return this.isUsernameValid ?
'Username is valid' :
'Username must be at least 3 characters'
}
}
}
</script>
<style>
.error {
color: red;
}
.success {
color: green;
}
</style>
2. Dynamic Heading Levels
You can use v-text
to set content for headings or other elements that require dynamic text:
<template>
<div>
<h1 v-text="pageTitle"></h1>
<div class="notification" v-text="notificationText"></div>
<!-- Dynamic content based on component props -->
<component
:is="'h' + headingLevel"
v-text="headingText"
></component>
</div>
</template>
<script>
export default {
props: {
headingLevel: {
type: Number,
default: 2,
validator: val => val >= 1 && val <= 6
},
headingText: {
type: String,
required: true
}
},
data() {
return {
pageTitle: 'Welcome to My App',
notificationText: 'You have 3 new messages'
}
}
}
</script>
3. Internationalization (i18n)
The v-text
directive works well with internationalization libraries to display translated text:
<template>
<div>
<h1 v-text="$t('welcome.title')"></h1>
<p v-text="$t('welcome.message', { name: username })"></p>
<select v-model="currentLanguage">
<option value="en">English</option>
<option value="es">Spanish</option>
<option value="fr">French</option>
</select>
</div>
</template>
<script>
export default {
data() {
return {
username: 'John',
currentLanguage: 'en'
}
},
watch: {
currentLanguage(newLang) {
this.$i18n.locale = newLang
}
}
}
</script>
Best Practices
When using the v-text
directive, consider these best practices:
Use v-text
when:
- You need to completely replace an element's text content
- You want to avoid "mustache flashing" (seeing raw template syntax before Vue compiles it)
- You're working with sensitive text that must never have HTML interpreted
Use mustache syntax {{ }}
when:
- Mixing dynamic values with static text
- Working with complex template expressions that are easier to read inline
- Creating templates that need to be readable to designers or non-Vue developers
Avoid using v-text
for:
- HTML content (use
v-html
instead, but be careful with XSS vulnerabilities) - Complex formatting (consider computed properties instead)
Security Considerations
The v-text
directive automatically escapes HTML content, which helps prevent XSS (Cross-Site Scripting) attacks. This means if your data contains HTML tags, they will be displayed as literal text, not rendered as HTML.
For example:
<template>
<div>
<p v-text="message"></p>
</div>
</template>
<script>
export default {
data() {
return {
message: '<strong>This will not be bold</strong>'
}
}
}
</script>
This will display the literal string <strong>This will not be bold</strong>
instead of rendering the bold text.
Common Mistakes
1. Trying to Use HTML
A common error is attempting to use the v-text
directive to render HTML content:
<!-- ❌ Incorrect: HTML tags will display as text -->
<div v-text="'<em>Emphasized</em> text'"></div>
<!-- ✅ Correct: Use v-html (but be aware of security implications) -->
<div v-html="'<em>Emphasized</em> text'"></div>
<!-- ✅ Alternative: Use mustache syntax with computed properties -->
<div>{{ formattedText }}</div>
2. Overriding Child Content
Another common mistake is not realizing that v-text
replaces all child content:
<!-- ❌ Incorrect: Content will be replaced by the value of greeting -->
<div v-text="greeting">
This content will be replaced entirely
<span>Including this span</span>
</div>
<!-- ✅ Correct: Use mustache syntax for partial content -->
<div>
{{ greeting }}
<span>This span will remain</span>
</div>
Performance Considerations
The v-text
directive is generally very efficient as it directly updates the element's textContent
property. However, for very large text content or frequent updates, consider these optimizations:
- Use computed properties for complex text transformations
- Apply
v-once
alongsidev-text
if the content will never change - For long lists, consider using
v-for
withkey
to help Vue optimize rendering
<template>
<div>
<!-- For static content that won't change -->
<p v-once v-text="staticDescription"></p>
<!-- For dynamic content that changes infrequently -->
<p v-text="dynamicDescription"></p>
<!-- For frequently changing content, use computed properties -->
<p v-text="formattedTimestamp"></p>
</div>
</template>
<script>
export default {
data() {
return {
staticDescription: 'This content never changes',
timestamp: Date.now()
}
},
computed: {
dynamicDescription() {
return `Updated content as of ${new Date().toLocaleTimeString()}`
},
formattedTimestamp() {
// Complex formatting logic here
return new Date(this.timestamp).toLocaleString()
}
},
mounted() {
setInterval(() => {
this.timestamp = Date.now()
}, 1000)
}
}
</script>
Summary
The v-text
directive is a fundamental Vue.js feature that allows developers to render text content dynamically. While similar to the mustache syntax ({{ }}
), it offers some distinct advantages such as avoiding the "flash of uncompiled content" and completely replacing an element's text.
Key points to remember:
- Use
v-text="expression"
to set an element's text content - Any valid JavaScript expression can be used with
v-text
- HTML content is escaped for security
v-text
replaces the entire content of an element- For mixed static/dynamic content, mustache syntax is often more appropriate
By understanding when and how to use the v-text
directive, you can create more dynamic and responsive Vue applications while maintaining good performance and security practices.
Additional Resources
To deepen your understanding of Vue.js directives, check out these resources:
- Vue.js Official Documentation on Directives
- Vue.js Guide on Template Syntax
- Vue.js API Documentation
Practice Exercises
- Create a simple Vue component that uses
v-text
to display a counter that increments every second. - Build a form validation example that uses
v-text
to show validation messages for different input fields. - Compare the performance of
v-text
vs. mustache syntax for rendering large text content. - Create a component that toggles between using
v-text
andv-html
to demonstrate the difference in rendering behavior.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)