YouTip LogoYouTip

Vue3 Blog Lifecycle Fetch

Life Cycle and Data Fetching |

\\n\\n

What is the Life Cycle?

\\n\\n

Each Vue component goes through a series of stages from creation to destruction, collectively known as the "life cycle".

\\n\\n

Vue provides corresponding lifecycle hooks at each stage, allowing you to execute code at specific moments.

\\n\\n

For example, if you want to fetch data after the component finishes loading, you need to use the onMounted hook.

\\n\\n

Overview of Vue3 Lifecycle Hooks

\\n\\n\\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
Hook FunctionExecution TimingCommon Use Cases
setup()Component initialization, executed firstDefine reactive data, computed properties
onBeforeMountBefore the component is mounted to the DOMRarely used
onMountedAfter the component is mounted to the DOMInitiate network requests, initialize third-party libraries, get DOM references
onBeforeUpdateBefore data changes and DOM updateRarely used
onUpdatedAfter data changes and DOM updatePerform operations after DOM update
onBeforeUnmountBefore the component is destroyedClear timers, cancel subscriptions, remove event listeners
onUnmountedAfter the component is destroyedConfirm cleanup tasks
\\n\\n

For blog projects, the most commonly used hook is onMountedβ€”to fetch article data after the page loads.

\\n\\n
\\n

Life cycle hooks must be written inside <script setup>, and cannot be placed inside asynchronous functions or conditional statements. Vue determines which component they belong to based on the call order.

\\n
\\n\\n

Basic Usage of onMounted

\\n\\n

Example

\\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\\n

A component can call onMounted multiple times, and they will execute in the order they were registered.

\\n\\n

Loading JSON Data with fetch

\\n\\n

We will place article data into a JSON file and load it using fetch inside onMounted.

\\n\\n

Step 1: Create the Data File

\\n\\n

Example

\\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

The JSON file is placed in the public/ directory. Vite serves it directly as a static file. In the browser, you can access it directly via /posts.json. Files in public/ are not compiled; they are copied as-is into the build output.

\\n
\\n\\n

Step 2: Fetch Data in the Component

\\n\\n

Example

\\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\\n
\\n\\n

Latest Posts

\\n\\n\\n\\n

Loading,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\\n
\\n\\n
\\n\\n
\\n\\n .status-msg {\\n\\n text-align: center;\\n\\n padding: 60px 0;\\n\\n font-size: 16px;\\n\\n color: #999;\\n\\n }\\n\\n .error { color: #e74c3c; }\\n\\n .error button {\\n\\n margin-left: 10px;\\n\\n padding: 4px 12px;\\n\\n cursor: pointer;\\n\\n }\\n\\n

Handling Three States of Asynchronous Requests

\\n\\n

Any data request should cover the following three UI states; otherwise, the user experience will be poor:

\\n\\n\\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
StateWhen It OccursUI Representation
LoadingAfter request is sent, before response returnsLoading animation, skeleton screen
SuccessData returns correctlyRender content normally
FailureNetwork error, server exceptionError message + retry button
\\n\\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\\n

Hands-on: Also Use fetch for the Detail Page

\\n\\n

The detail page needs to find the corresponding article from the JSON based on the ID in the URL.

\\n\\n

You can reuse the data loading logicβ€”call fetch again on the detail page, then filter the result.

\\n\\n

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\\n
\\n\\n

Loading...

\\n\\n

Load failed:{{ error }}

\\n\\n
\\n\\n

Post not found

\\n\\n
\\n\\n
\\n\\n{{ article.category }}\\n\\n

{{ article.title }}

\\n\\n\\n\\n
\\n\\n← \\n\\n
\\n\\n
\\n\\n

Chapter Summary

\\n\\n

In 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).

\\n\\n

Now, blog data is loaded asynchronously from an external JSON file, closely resembling real-world project workflows.

← Flask Blog WtfFlask Blog Search Pagination β†’