📖 Scenario: You are building a Vue 3 app that manages user profile data. Some parts of the data should not be changed by child components to avoid accidental updates.
🎯 Goal: Create a reactive user profile object and make it immutable using Vue's readonly function. Then pass this readonly data to a child component to ensure it cannot be modified.
📋 What You'll Learn
Create a reactive object called userProfile with keys name and age and values 'Alice' and 30
Create a readonly version of userProfile called immutableProfile
Use immutableProfile in the template to display the user's name and age
Pass immutableProfile as a prop to a child component called UserCard
💡 Why This Matters
🌍 Real World
In real apps, some data should be protected from changes by child components to avoid bugs. Using readonly helps enforce this immutability.
💼 Career
Understanding reactive and readonly data is essential for Vue developers to manage state safely and build maintainable applications.
Progress0 / 4 steps
1
Create reactive user profile data
Create a reactive object called userProfile with keys name set to 'Alice' and age set to 30 using Vue's reactive function.
Vue
Hint
Use const userProfile = reactive({ name: 'Alice', age: 30 }) to create the reactive object.
2
Create readonly immutable profile
Import Vue's readonly function and create a readonly version of userProfile called immutableProfile.
Vue
Hint
Use const immutableProfile = readonly(userProfile) to create the immutable reactive object.
3
Display immutable profile data in template
Use immutableProfile.name and immutableProfile.age inside the template to display the user's name and age in paragraphs.
Vue
Hint
Use mustache syntax like {{ immutableProfile.name }} inside paragraph tags.
4
Pass immutable profile to child component
Create a child component called UserCard and pass immutableProfile as a prop named profile to it in the template.
Vue
Hint
Use <UserCard :profile="immutableProfile" /> to pass the readonly data as a prop.
Practice
(1/5)
1. What does the readonly function do in Vue's reactivity system?
easy
A. It creates an immutable reactive object that cannot be changed directly.
B. It makes a reactive object completely non-reactive and static.
C. It clones the reactive object and allows changes only on the clone.
D. It converts a reactive object into a plain JavaScript object.
Solution
Step 1: Understand the purpose of readonly
The readonly function wraps a reactive object to prevent direct modifications, making it immutable.
Step 2: Compare with other behaviors
Unlike cloning or removing reactivity, readonly keeps the object reactive but disallows changes.
Final Answer:
It creates an immutable reactive object that cannot be changed directly. -> Option A
Quick Check:
Readonly = Immutable reactive object [OK]
Hint: Readonly means no direct changes allowed on reactive data [OK]
Common Mistakes:
Thinking readonly removes reactivity completely
Assuming readonly clones data instead of wrapping
Believing readonly allows changes on the wrapped object
2. Which of the following is the correct way to create a readonly reactive object in Vue?
easy
A. const data = readonly({ count: 0 })
B. const data = readonly(reactive({ count: 0 }))
C. const data = reactive(readonly({ count: 0 }))
D. const data = reactive({ count: 0 }).readonly()
Solution
Step 1: Understand the correct usage order
You first create a reactive object, then wrap it with readonly to make it immutable.
Step 2: Evaluate each option
const data = readonly(reactive({ count: 0 })) correctly wraps a reactive object with readonly. const data = reactive(readonly({ count: 0 })) tries to make a readonly object reactive, which is invalid. const data = readonly({ count: 0 }) skips reactive, so no reactivity. const data = reactive({ count: 0 }).readonly() uses a non-existent method.
Final Answer:
const data = readonly(reactive({ count: 0 })) -> Option B
Quick Check:
Wrap reactive with readonly = const data = readonly(reactive({ count: 0 })) [OK]
Hint: Wrap reactive() inside readonly() to make immutable reactive [OK]
Common Mistakes:
Calling readonly before reactive
Skipping reactive and only using readonly
Using non-existent readonly method on reactive
3. Given the code below, what will be logged to the console?
Step 1: Understand readonly behavior on assignment
Assigning to readOnlyState.count causes a warning in development mode, but the change is ignored and value remains 1.
Step 2: Check reactive source update reflection
First console.log(readOnlyState.count) outputs 1. Changing state.count to 10 updates the source, so second log is 10.
Final Answer:
1 and 10 -> Option D
Quick Check:
Readonly warns/ignores direct change, reflects source updates [OK]
Hint: Readonly blocks direct changes but shows source updates [OK]
Common Mistakes:
Expecting readonly to allow direct assignment
Thinking readonly copies data instead of reflecting source
Ignoring error/warning on assignment to readonly
4. Identify the error in the following Vue code using readonly:
import { reactive, readonly } from 'vue';
const data = readonly({ count: 0 });
data.count = 1;
console.log(data.count);
medium
A. You cannot assign to a readonly object directly.
B. You must use ref() instead of reactive() for readonly.
C. Readonly does not exist in Vue's API.
D. You must wrap a reactive object with readonly, not a plain object.
Solution
Step 1: Check how readonly is used
The code creates a readonly proxy but then attempts data.count = 1.
Step 2: Understand readonly requirements
Readonly prevents direct mutations, causing a development warning and ignoring the assignment.
Final Answer:
You cannot assign to a readonly object directly. -> Option A
Quick Check:
Cannot mutate readonly objects [OK]
Hint: Readonly objects cannot be mutated directly [OK]
Common Mistakes:
Attempting to mutate readonly objects directly
Assuming readonly works without reactive
Confusing readonly with ref
5. You have a reactive object state shared across components. You want to expose it as readonly to prevent accidental changes but still reflect updates. Which approach correctly achieves this and why?
const state = reactive({ user: { name: 'Alice' }, count: 0 });
// Options:
// A) const safeState = readonly(state);
// B) const safeState = reactive(state);
// C) const safeState = readonly({ ...state });
// D) const safeState = reactive(readonly(state));
hard
A. Create a shallow copy and make it readonly, but it won't reflect nested updates.
B. Wrap the reactive state with readonly to prevent direct changes but reflect updates.
C. Wrap the state again with reactive, which allows changes and duplicates reactivity.
D. Wrap readonly with reactive, which is invalid and causes errors.
Solution
Step 1: Analyze each option's effect
Wrap the reactive state with readonly to prevent direct changes but reflect updates. correctly wraps the reactive object with readonly, making it immutable but still reactive to source changes. Wrap the state again with reactive, which allows changes and duplicates reactivity. duplicates reactivity and allows changes. Create a shallow copy and make it readonly, but it won't reflect nested updates. creates a shallow copy, losing nested reactivity. Wrap readonly with reactive, which is invalid and causes errors. is invalid usage.
Step 2: Confirm correct approach for safe sharing
Readonly wrapping reactive is the recommended way to share data safely without allowing modifications but reflecting updates.
Final Answer:
Wrap the reactive state with readonly to prevent direct changes but reflect updates. -> Option C
Quick Check:
Readonly wraps reactive for safe, immutable sharing [OK]
Hint: Wrap reactive with readonly to share immutable reactive data [OK]