App.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
<template> <div class="vl-parent"> <!-- Spinner --> <loading v-model:active="isLoading" :can-cancel="true" :on-cancel="onCancel" :is-full-page="fullPage" /> <!-- Fetch Data Button --> <button @click.prevent="doAjax">Fetch Data</button> <!-- Fetched Data --> <div v-if="showData" class="data-display"> <h3>Fetched Data:</h3> <ul> <li v-for="(post, index) in fetchedData" :key="index"> <strong>{{ post.title }}</strong>: {{ post.body }} </li> </ul> </div> </div> </template> <script> import Loading from 'vue-loading-overlay'; import 'vue-loading-overlay/dist/css/index.css'; export default { data() { return { isLoading: false, // Controls spinner visibility fullPage: true, // Full-page spinner fetchedData: [], // Stores fetched data showData: false, // Controls when data is displayed }; }, components: { Loading, }, methods: { async doAjax() { this.isLoading = true; // Show spinner this.showData = false; // Hide data until spinner is hidden const fetchStart = Date.now(); // Start measuring fetch time try { const response = await fetch('https://jsonplaceholder.typicode.com/posts'); if (!response.ok) { throw new Error('Network response was not ok'); } this.fetchedData = await response.json(); } catch (error) { console.error('Error fetching data:', error); alert('Failed to fetch data. Please try again.'); } finally { const elapsed = Date.now() - fetchStart; const remainingTime = Math.max(3000 - elapsed, 0); // Ensure at least 3 seconds setTimeout(() => { this.isLoading = false; // Hide spinner this.showData = true; // Show data only after spinner is hidden }, remainingTime); } }, onCancel() { console.log('User cancelled the loader.'); this.isLoading = false; // Allow user to cancel loading }, }, }; </script> <style> .vl-parent { text-align: center; margin-top: 50px; } .data-display { margin-top: 20px; text-align: left; max-width: 600px; margin: 20px auto; background-color: #f9f9f9; padding: 15px; border: 1px solid #ddd; border-radius: 5px; } .data-display h3 { margin-bottom: 10px; } .data-display ul { list-style: none; padding: 0; } .data-display li { margin-bottom: 10px; padding: 5px; border-bottom: 1px solid #eee; } </style> |