Vue Computed Properties

Efficient reactive calculations in Vue

⚡ What are Computed Properties?

Computed properties are cached reactive values based on their dependencies. They automatically update when dependencies change and are more efficient than methods for complex calculations.


<div id="app">
    <p>{{ fullName }}</p>
</div>

<script src="https://unpkg.com/vue@3"></script>
<script>
    Vue.createApp({
        data() {
            return {
                firstName: 'John',
                lastName: 'Doe'
            }
        },
        computed: {
            fullName() {
                return this.firstName + ' ' + this.lastName
            }
        }
    }).mount('#app')
</script>
                                    

Computed Properties Benefits

💾

Cached

Results are cached until dependencies change

🔄

Reactive

Automatically updates when data changes

Efficient

Only recalculates when needed

📖

Readable

Cleaner template syntax than methods

🔹 Basic Computed Property

Computed properties are defined in the computed option. They work like data properties but are calculated based on other reactive data.

<div id="app">
    <input v-model="firstName" placeholder="First name">
    <input v-model="lastName" placeholder="Last name">
    <p>Full Name: {{ fullName }}</p>
    <p>Reversed: {{ reversedName }}</p>
</div>

<script src="https://unpkg.com/vue@3"></script>
<script>
    Vue.createApp({
        data() {
            return {
                firstName: 'John',
                lastName: 'Doe'
            }
        },
        computed: {
            fullName() {
                return this.firstName + ' ' + this.lastName
            },
            reversedName() {
                return this.fullName.split('').reverse().join('')
            }
        }
    }).mount('#app')
</script>

Output:

Full Name: John Doe

Reversed: eoD nhoJ

🔹 Computed vs Methods

While methods and computed properties can achieve similar results, computed properties are cached and only re-evaluate when dependencies change, making them more efficient.

Key Differences:

  • Computed: Cached, only recalculates when dependencies change
  • Methods: Always runs when called, no caching
  • Use Computed: For calculations based on reactive data
  • Use Methods: For actions or when you need to pass parameters
<div id="app">
    <p>Computed: {{ computedPrice }}</p>
    <p>Method: {{ calculatePrice() }}</p>
    <button @click="quantity++">Add Item</button>
</div>

<script src="https://unpkg.com/vue@3"></script>
<script>
    Vue.createApp({
        data() {
            return {
                price: 10,
                quantity: 1
            }
        },
        computed: {
            computedPrice() {
                console.log('Computed called')
                return this.price * this.quantity
            }
        },
        methods: {
            calculatePrice() {
                console.log('Method called')
                return this.price * this.quantity
            }
        }
    }).mount('#app')
</script>

🔹 Computed Property with Getter and Setter

Computed properties can have both getter and setter functions. This allows you to modify the computed value, which then updates the underlying data.

<div id="app">
    <input v-model="fullName" placeholder="Enter full name">
    <p>First: {{ firstName }}</p>
    <p>Last: {{ lastName }}</p>
</div>

<script src="https://unpkg.com/vue@3"></script>
<script>
    Vue.createApp({
        data() {
            return {
                firstName: 'John',
                lastName: 'Doe'
            }
        },
        computed: {
            fullName: {
                // Getter
                get() {
                    return this.firstName + ' ' + this.lastName
                },
                // Setter
                set(newValue) {
                    const names = newValue.split(' ')
                    this.firstName = names[0]
                    this.lastName = names[names.length - 1]
                }
            }
        }
    }).mount('#app')
</script>

Output:

First: John

Last: Doe

🔹 Practical Example: Shopping Cart

Here's a practical example using computed properties to calculate shopping cart totals:

<div id="app">
    <h3>Shopping Cart</h3>
    <div v-for="item in items" :key="item.id">
        <span>{{ item.name }}: ${{ item.price }} x {{ item.quantity }}</span>
        <button @click="item.quantity++">+</button>
        <button @click="item.quantity--">-</button>
    </div>
    
    <p>Subtotal: ${{ subtotal }}</p>
    <p>Tax (10%): ${{ tax }}</p>
    <p><strong>Total: ${{ total }}</strong></p>
</div>

<script src="https://unpkg.com/vue@3"></script>
<script>
    Vue.createApp({
        data() {
            return {
                items: [
                    { id: 1, name: 'Book', price: 10, quantity: 2 },
                    { id: 2, name: 'Pen', price: 2, quantity: 5 }
                ]
            }
        },
        computed: {
            subtotal() {
                return this.items.reduce((sum, item) => {
                    return sum + (item.price * item.quantity)
                }, 0)
            },
            tax() {
                return (this.subtotal * 0.1).toFixed(2)
            },
            total() {
                return (parseFloat(this.subtotal) + parseFloat(this.tax)).toFixed(2)
            }
        }
    }).mount('#app')
</script>

Output:

Shopping Cart

Book: $10 x 2
Pen: $2 x 5

Subtotal: $30

Tax (10%): $3.00

Total: $33.00

🔹 Filtering and Sorting Lists

Computed properties are perfect for filtering and sorting data without modifying the original array:

<div id="app">
    <input v-model="searchQuery" placeholder="Search...">
    
    <ul>
        <li v-for="user in filteredUsers" :key="user.id">
            {{ user.name }} - {{ user.age }} years old
        </li>
    </ul>
</div>

<script src="https://unpkg.com/vue@3"></script>
<script>
    Vue.createApp({
        data() {
            return {
                searchQuery: '',
                users: [
                    { id: 1, name: 'Alice', age: 25 },
                    { id: 2, name: 'Bob', age: 30 },
                    { id: 3, name: 'Charlie', age: 22 },
                    { id: 4, name: 'David', age: 28 }
                ]
            }
        },
        computed: {
            filteredUsers() {
                return this.users.filter(user => {
                    return user.name.toLowerCase()
                        .includes(this.searchQuery.toLowerCase())
                })
            }
        }
    }).mount('#app')
</script>

Output:

  • Alice - 25 years old
  • Bob - 30 years old
  • Charlie - 22 years old
  • David - 28 years old

🧠 Test Your Knowledge

What is the main advantage of computed properties over methods?