iT邦幫忙

2025 iThome 鐵人賽

DAY 26
0
Vue.js

遊戲活動關卡查詢網站系列 第 26

遊戲活動關卡查詢網站Day26-歡迎來到本網站(Laoding載入)

  • 分享至 

  • xImage
  •  

目標
鐵人文即將進入尾聲
這篇將網站的功能收尾
會將前面做過的東西算是總複習再做一遍
我們這次要做的功能是畫面Loading的模擬
同時也會把一些金言佳句放在載入畫面上

大略會像下圖排版
加載畫面除了作為網站歡迎頁面外
在加載完成後
我也想讓它出現「金言佳句或一些心靈雞湯」

步驟
1.
同樣從畫面規劃開始
因為從Supabase取資料一定會一些延遲時間
所以需要做加載畫面
下圖是加載前的資料

下圖則為加載後的資料 同時呈現金言佳句的文章

底下是我們這次要用的Bootstrap元件-Modal
首先我們來看官方文件中的Demo
它實際上就是彈出視窗
但是我們要的是點背景不會關閉 而是按下X按鈕才關閉

雖然它有提供靜態背景的架構
不過我們還是需要另外調整
先回到父組件APP.vue
在template最上方加上以下程式架構

<template>
<!-- Loading Modal -->
<div v-if="modalOpen" class="modal fade show d-block bg-dark"  tabindex="-1" >
	<div class="modal-dialog modal-dialog-centered">
		<div class="modal-content text-center">
			<div class="modal-header">
			 <h5 class="modal-title">歡迎來到關卡查詢網站</h5>
				<!-- X 按鈕:僅當全部載入完成後才顯示 -->
				<button 
				type="button"  class="btn-close"
				@click="modalOpen = false">
				</button>
			</div>
			<div class="modal-body">
				<div class="row">
					<div class="col-6 bg-primary text-start"></div>
					<div class="col-6 bg-warning d-flex flex-column justify-content-center align-items-center">
						<div >
							<div class="spinner-border text-primary" role="status">
							</div>
							<p class="mt-2">資料載入中...</p>
						</div>
						<div>文字文字文字</div>
						<div class="mt-auto ms-auto">來源</div>
					</div>
				<div>
			<div>
				
			</div>


			</div>

			</div>
			</div>
		</div>
	</div>
</div>
//...以下略
</template>

現在畫面如下圖
依照剛才線稿的規劃
將資料載入動畫和文字內容放上

接著補上我們在Day24存的頭像

同時在script增加以下程式架構
就和我們之前讀取圖片網址做法相同
其中supportSettingImgUrl屬性
要另外再補上沒有設置頭像時 預設的圖片

<script setup>
//....中間略
import { useLocalStorageRef } from "./useLocalStorageRef.js"
const favoriteSupportSettingList = useLocalStorageRef("favoriteSupportSettingList");
const images = require.context('@/assets/Fairy', false,  /\.(png|jpg)$/)


const supportSettingImgUrl = computed(() => {
	return favoriteSupportSettingList.value.length !=  0 
	? images(`./${favoriteSupportSettingList.value["eventNo"]}.png`) 
	: images("./0000.jpg") ;
})
</script>

接下來
我們要控制關閉按鈕來關閉Modal元件
但是,關閉按鈕會在什麼時候出現呢?
所以會有以下情況判斷
關閉按鈕出現的條件是
全部子組件取Supabase的資料完畢 才會出現

由於B、D、S組件在初始載入時要連Supabase API
所以流程圖會像下面這樣
當子組件都取完資料後 告訴父組件完成了
父組件控制關閉按鈕的顯示

回到父組件這邊
我們預計的規劃如下
B組件載入完成=>emit傳回true=>LoadingB改為true
D組件載入完成=>emit傳回true=>LoadingD改為true
S組件載入完成=>emit傳回true=>LoadingS改為true
我們將script補上幾段
showClose是關閉按鈕的顯示
判斷loadingState裡的屬性是否都為true

<script setup>
const modalOpen = ref(true);
const loadingState = ref({
	LoadingB : false,
	LoadingD : false,
	LoadingS : false,
})

const showClose = computed(() => {
	return loadingState.value.LoadingB && 
			loadingState.value.LoadingD && 
			loadingState.value.LoadingS ;
})
</script>

同樣在template也補上幾個屬性
比較重要的是補上相對應的v-if屬性
去控制關閉按鈕、Modal視窗的顯示

接下來,我們要做的就是捕捉子組件載入的狀況
先在B組件做試試看
我們載入B組件的屬性 多加上下圖這個紅框
來捕捉B組件傳過來的資料

再來到B組件
這邊加一個emit
別忘記也要定義emit

<script setup>
const emit = defineEmits(["response","responseBF","responseBDisplay","responseBR","loading"]);
onMounted(async () => {
  const { data, error } = await supabase
    .from("action_event")
	.select("*")

  if (error) {
    console.error(error);
  } else {
    result.value = data;
	emit("responseBF", result.value);
	emit("responseBR", result.value);
	 setTimeout(() => {emit("loading", true)}, 3000)
  }
});
</script>

如下圖紅框 是修改的地方
由於資料取得的速度約略1秒左右 可能看不出差異
所以利用setTimeout特性
在3秒後emit送出「B組件取好資料了」的訊息

如下圖 取完資料後再等3秒出現關閉按鈕
接著我們把其他子組件也做相同的emit傳送

然後把金言佳句、心靈雞湯的句子也放進來
下圖資料這是在網路上抓的

我們在父組件template補上以下程式架構
同樣初次就載入
我們用getRandomSentence屬性
去取隨機的資料

<script setup>
const result = ref([]);
const getRandomSentence = computed(() => {
	const randomNumber = Math.floor(Math.random() * (result.value.length));
	return result.value[randomNumber]
})

onMounted(async () => {    //初次就載入資料
  const { data, error } = await supabase
    .from("dailygold")
	.select("*")

  if (error) {
    console.error(error);
  } else {
    result.value = data;
  }
});
</script>

template也跟著稍微調整如下圖

這一頁result讀取Supabase
而getRandomSentence的資料來源於result
一開始result沒有資料 它也會是空的
我們在這邊用v-if去判斷result

這邊有個重點是
如果v-if 為false
Vue在渲染時 就不會建立這個虛擬DOM節點
即使getRandomSentence這個時候沒有東西
但因為這個節點一開始本來就不存在
裡面這層的插值表達式{{getRandomSentence}}不會被求值
也就不會導致程式報錯的問題

下圖就是我們這次的成果
使用者每次打開網路都會顯示不同句子
按下關閉按鈕 就回到我們網站了

這篇做了網站程式架構的收尾
讓它已經有了初步的雛型
接下來最後幾篇,我們要做網站上傳的準備工作
讓外部網路也能連到。

備註
1.
剛才有提到
因為圖片的引入是看Assets底下的檔案
所以由於父組件和子組件檔案放置路徑不同
引入的路徑也會和子組件有差異
其他段的引入也會需要注意到哦

因為Supabase有效能與安全考量
預設資料在1000筆
無論你條件是什麼 都只會回1000筆
所以如果需要一次取超過1000筆的資料
我們可以到API Setting這邊做設定


上一篇
遊戲活動關卡查詢網站Day25-支援名單2(event)
下一篇
遊戲活動關卡查詢網站Day27-上傳網站1(Github+SourceTree)
系列文
遊戲活動關卡查詢網站30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言