Life Cycle and Data Fetching |
\\n\\nWhat is the Life Cycle?
\\n\\nEach Vue component goes through a series of stages from creation to destruction, collectively known as the "life cycle".
\\n\\nVue provides corresponding lifecycle hooks at each stage, allowing you to execute code at specific moments.
\\n\\nFor example, if you want to fetch data after the component finishes loading, you need to use the onMounted hook.
Overview of Vue3 Lifecycle Hooks
\\n\\n| Hook Function | \\nExecution Timing | \\nCommon Use Cases | \\n
|---|---|---|
setup() | \\n Component initialization, executed first | \\nDefine reactive data, computed properties | \\n
onBeforeMount | \\n Before the component is mounted to the DOM | \\nRarely used | \\n
onMounted | \\n After the component is mounted to the DOM | \\nInitiate network requests, initialize third-party libraries, get DOM references | \\n
onBeforeUpdate | \\n Before data changes and DOM update | \\nRarely used | \\n
onUpdated | \\n After data changes and DOM update | \\nPerform operations after DOM update | \\n
onBeforeUnmount | \\n Before the component is destroyed | \\nClear timers, cancel subscriptions, remove event listeners | \\n
onUnmounted | \\n After the component is destroyed | \\nConfirm cleanup tasks | \\n
For blog projects, the most commonly used hook is onMountedβto fetch article data after the page loads.
\\n\\n\\nLife cycle hooks must be written inside
\\n<script setup>, and cannot be placed inside asynchronous functions or conditional statements. Vue determines which component they belong to based on the call order.
Basic Usage of onMounted
\\n\\nExample
\\n\\n import { ref, onMounted } from 'vue'\\n\\nconst message = ref('Loading...')\\n\\n// onMounted Executed after the component is mounted to the page\\n\\n onMounted(() => {\\n\\n // At this point, the DOM has finished rendering, making it safe to manipulate the DOM or send requests.\\n\\n console.log('Component mounted, ready to start loading data')\\n\\n message.value = 'Data loaded!'\\n\\n })\\n\\n{{ message }}
\\n\\nA component can call onMounted multiple times, and they will execute in the order they were registered.
Loading JSON Data with fetch
\\n\\nWe will place article data into a JSON file and load it using fetch inside onMounted.
Step 1: Create the Data File
\\n\\nExample
\\n\\n// File path: public/posts.json\\n\\n [\\n\\n {\\n\\n "id": 1,\\n\\n "title": "Vue3 Getting StartedComplete Guide",\\n\\n "summary": "Learn Vue3 Composition API from scratch, covering core concepts like ref, reactive, computed, etc.",\\n\\n "content": "<h2>Why learn Vue3?</h2><p>Vue3 is one of the most popular frontend frameworks today...</p>",\\n\\n "category": "Vue",\\n\\n "date": "2024-05-10"\\n\\n },\\n\\n {\\n\\n "id": 2,\\n\\n "title": "JavaScript Asynchronous Programming Explained",\\n\\n "summary": "Understand Promise, async/await, event loop, and microtask queue in one article.",\\n\\n "content": "<h2>What is asynchronous?</h2><p>JS is single-threaded...</p>",\\n\\n "category": "JavaScript",\\n\\n "date": "2024-05-08"\\n\\n },\\n\\n {\\n\\n "id": 3,\\n\\n "title": "CSS Grid Layout in Practice",\\n\\n "summary": "Use CSS Grid Easily implement complex responsive layouts.",\\n\\n "content": "<h2>Grid Getting Started</h2><p>Grid is a two-dimensional layout system...</p>",\\n\\n "category": "CSS",\\n\\n "date": "2024-05-05"\\n\\n }\\n\\n ]\\n\\n\\n\\n\\n\\n\\nThe JSON file is placed in the
\\npublic/directory. Vite serves it directly as a static file. In the browser, you can access it directly via/posts.json. Files inpublic/are not compiled; they are copied as-is into the build output.
Step 2: Fetch Data in the Component
\\n\\nExample
\\n\\n\\n\\n import { ref, onMounted } from 'vue'\\n\\n import BlogCard from '../components/BlogCard.vue'\\n\\n import CategoryFilter from '../components/CategoryFilter.vue'\\n\\nconst articles = ref([]) // Initial empty array\\n\\n const isLoading = ref(true) // Loading state\\n\\n const error = ref(null) // Error message\\n\\n// Asynchronously load article data\\n\\n async function fetchPosts() {\\n\\n isLoading.value = true\\n\\n error.value = null\\n\\n try {\\n\\n const response = await fetch('/posts.json')\\n\\n // Check if the response is successful (throw an error on 404 or 500)\\n\\n if (!response.ok) {\\n\\n throw new Error(`Load failedοΌHTTP ${response.status}`)\\n\\n }\\n\\n const data = await response.json()\\n\\n articles.value = data\\n\\n } catch (err) {\\n\\n error.value = err.message\\n\\n console.error('Failed to load post data:', err)\\n\\n } finally {\\n\\n isLoading.value = false\\n\\n }\\n\\n }\\n\\n// Load data immediately after component mount\\n\\n onMounted(() => {\\n\\n fetchPosts()\\n\\n })\\n\\nLatest Posts
\\n\\n\\n\\nLoadingοΌPlease wait...
\\n\\n\\n\\n\\n\\n Load failedοΌ{{ error }}\\n\\n\\n\\n
\\n\\n\\n\\n\\n\\n No posts yet, stay tuned.\\n\\n
\\n\\n\\n\\nHandling Three States of Asynchronous Requests
\\n\\nAny data request should cover the following three UI states; otherwise, the user experience will be poor:
\\n\\n| State | \\nWhen It Occurs | \\nUI Representation | \\n
|---|---|---|
| Loading | \\nAfter request is sent, before response returns | \\nLoading animation, skeleton screen | \\n
| Success | \\nData returns correctly | \\nRender content normally | \\n
| Failure | \\nNetwork error, server exception | \\nError message + retry button | \\n
You can also handle a fourth stateβempty data (request succeeds but returns an empty array)βto give users a clear message instead of a blank page.
\\n\\nHands-on: Also Use fetch for the Detail Page
\\n\\nThe detail page needs to find the corresponding article from the JSON based on the ID in the URL.
\\n\\nYou can reuse the data loading logicβcall fetch again on the detail page, then filter the result.
Example
\\n\\n\\n\\n import { ref, computed, onMounted } from 'vue'\\n\\n import { useRoute, RouterLink } from 'vue-router'\\n\\nconst route = useRoute()\\n\\n const id = Number(route.params.id)\\n\\nconst posts = ref([]) // All Posts\\n\\n const isLoading = ref(true)\\n\\n const error = ref(null)\\n\\n// Find current post by ID\\n\\n const article = computed(() => {\\n\\n return posts.value.find(p => p.id === id)\\n\\n })\\n\\n// Load All Posts Data\\n\\n async function fetchPosts() {\\n\\n isLoading.value = true\\n\\n try {\\n\\n const res = await fetch('/posts.json')\\n\\n if (!res.ok) throw new Error('Load failed')\\n\\n posts.value = await res.json()\\n\\n } catch (err) {\\n\\n error.value = err.message\\n\\n } finally {\\n\\n isLoading.value = false\\n\\n }\\n\\n }\\n\\nonMounted(() => {\\n\\n fetchPosts()\\n\\n })\\n\\nLoading...
\\n\\nLoad failedοΌ{{ error }}
\\n\\nPost not found
\\n\\n{{ article.title }}
\\n\\n\\n\\n\\n\\nβ \\n\\nChapter Summary
\\n\\nIn this chapter, you mastered the core onMounted lifecycle hook in Vue3, loading JSON data from the public directory using fetch, and handling the four UI states of requests (loading, success, failure, empty).
Now, blog data is loaded asynchronously from an external JSON file, closely resembling real-world project workflows.
YouTip