Watching for deeply nested object states and props is something that we often have to do in a Vue.js app.
In this article, we’ll look at how to properly watch for nested data in Vue.js components.
Deep Watchers
We can add deep watchers to components within the watch
property.
For instance, we can write:
App.vue
<template>
<div id="app">
<button
@click="
id++;
getTodo(id);
"
>
increment id
</button>
<Todo :todo="todo" />
</div>
</template>
<script>
import Todo from "./components/Todo";
export default {
name: "App",
components: {
Todo,
},
data() {
return {
todo: {},
id: 1,
};
},
methods: {
async getTodo(id) {
const results = await fetch(
`https://jsonplaceholder.typicode.com/todos/${id}`
);
const data = await results.json();
this.todo = data;
},
},
};
</script>
Todo.vue
<template>
<div class="hello"></div>
</template>
<script>
export default {
name: "Todo",
props: {
todo: Object,
},
watch: {
todo: {
handler(val) {
console.log(val);
},
deep: true,
},
},
};
</script>
We have a button that calls getTodo
when we get it to get a new todo
object with the given id
.
getTodo
updates the todo
reactive property from the response.
We pass the todo
value to the todo
prop of the Todo
component.
Then in the Todo
component, we watch the todo
prop with the watch
property.
We have the handler
function with the val
parameter to get the latest value.
deep
is set to true
so that we can watch for properties object props.
Computed Property
We can create a computed property to get the property from a reactive property.
For instance, we can write:
Todo.vue
<template>
<div>{{ todoTitle }}</div>
</template>
<script>
export default {
name: "Todo",
props: {
todo: Object,
},
computed: {
todoTitle() {
return this.todo.title;
},
},
};
</script>
We keep App.vue
the same.
We created the todoTitle
computed property that returns the this.todo.title
property.
Then we can use it in the template like any other reactive property.
todoTitle
will be updated whenever any property in the this.todo
object is updated.
Watch a Property of an Object
We can also watch a property of an object.
For instance, we can write:
<template>
<div class="hello"></div>
</template>
<script>
export default {
name: "Todo",
props: {
todo: Object,
},
watch: {
"todo.title": {
handler(val) {
console.log(val);
},
},
},
};
</script>
Then the title
property from the todo
prop is watched with the watcher.
This is because 'todo.title'
is the title
property of the todo
prop.
val
would have the value of the title
property of the todo
prop.
We can get the newVal
and oldVal
from the watcher function:
<template>
<div class="hello"></div>
</template>
<script>
export default {
name: "Todo",
props: {
todo: Object,
},
watch: {
"todo.title": {
handler(newVal, oldVal) {
console.log(newVal, oldVal);
},
},
},
};
</script>
Conclusion
We can watch for nested properties with watchers by adding methods to the watch
property object with a property path.
Also, we can set deep
to true
to watch for deeply nested properties.