iT邦幫忙

2025 iThome 鐵人賽

DAY 15
0
Vue.js

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

遊戲活動關卡查詢網站Day15-敵人資訊1(Vue:Watch)

  • 分享至 

  • xImage
  •  

目標
現在點擊關卡(例如4-1、5-1)時
A組件會顯示敵人資訊
運用前兩天學習的Emits(子傳父)、Props(父傳子)
將C組件選取的資料傳到A組件
這篇會建立Supabase的函式
並利用條件取得敵人資訊

步驟
1
如同之前資料傳給父組件的方式
在C組件這邊也做一遍
在點擊關卡時
將actionNo、eventNo、stagePrimaryNo、stageSecNo傳給父組件


//...以上略
<script setup>
/* global defineEmits */
const emit = defineEmits(["response"]);

//點擊副本關卡事件
function selectEvent(e) {

	const data = {
						"actionNo":props.msg.actionNo,
						"eventNo":e.target.getAttribute("data-eventNo"),
						"stagePrimaryNo":e.target.getAttribute("data-stagePrimaryNo"),
						"stageSecNo":e.target.getAttribute("data-stageSecNo")
	};
	emit("response", data);
}

</script>

同樣的template也加上要傳出去的資訊

//...中間略
<template>
				<ul class="list-group list-group-flush">
					<li class="list-group-item" v-for="child in item.eventInfo" :key="child"
					:data-eventNo="item.eventNo" :data-stagePrimaryNo="child.substring(0,2)" 
					:data-stageSecNo="child.substring(2,4)" @click="selectEvent"
					>
					{{ String(parseInt(child.substring(0,2))).padStart(2, ' ')}}
						-
					{{ String(parseInt(child.substring(2,4))).padStart(2, ' ')}}
					</li>
				</ul>
</template>

2
父組件(APP.vue)也同樣在這邊監聽
如果C組件傳過來的資料有改變,就變更C_Msg

//....中間略
<template>
  <C-event :msg="B_Msg"  @response="(msg) => C_Msg = msg" />
</template>

<script setup>
//...中間略
const C_Msg = ref([{}]); 
</script>

當中由A組件組成的部分
也把C_Msg傳進去

<A-enemy :msg="C_Msg"/>

3
在A組件 透過Props去接
此時接到msg後,我們用這筆資料去拿敵人資訊
這時候,就要去連Supabase的API

<script setup>
/* global defineProps */
import { ref,computed,watch } from "vue";
import { supabase } from "../supabase.js";
const result = ref([]);
const props = defineProps({
  msg: Object
})
</script>

4
首先,因為要連Supabase
我們要去用msg資料這個條件去找
所以需要先建立Supabase的函式
我們回到Supabase這邊使用語法建立函式
待會會用這個函式查詢資料

CREATE OR REPLACE FUNCTION getenemy_byevent(p_rrn text)
RETURNS TABLE(
    stageOrder text,
    actionName text,
    eventName text,
    element text,
    species text,
    hp text,
    angerCondition text,
    skillOrder bigint,
    rrn text,
    skillFlag text,
    skill1Name text,
    skill1Value text,
    skill1Unit text,
    skill1Target text,
    skill1Time text,
    skill2Name text,
    skill2Value text,
    skill2Unit text,
    skill2Target text,
    skill2Time text,
    skill3Name text,
    skill3Value text,
    skill3Unit text,
    skill3Target text,
    skill3Time text
)
AS $$
  SELECT  
    action_event."stageOrder",
    action_event."actionName",
    action_event."eventName",
    enemy."element",
    enemy."species",
    enemy."hp",
    enemy."angerCondition",
    skill."skillOrder" ,
    enemy."rrn" || enemy."posNo",
    skill."skillFlag",
    skill."skill1Name",
    skill."skill1Value",
    skill."skill1Unit",
    skill."skill1Target",
    skill."skill1Time",
    skill."skill2Name",
    skill."skill2Value",
    skill."skill2Unit",
    skill."skill2Target",
    skill."skill2Time",
    skill."skill3Name",
    skill."skill3Value",
    skill."skill3Unit",
    skill."skill3Target",
    skill."skill3Time"
  FROM action_event
  LEFT JOIN enemy  
    ON (action_event."actionNo" || action_event."eventNo" || action_event."stagePrimaryNo" 
        || action_event."stageSecNo" || action_event."stageOrder") = enemy."rrn"
  LEFT JOIN skill  
    ON (enemy."rrn" || enemy."posNo") = skill."rrn"
  WHERE (action_event."actionNo" || action_event."eventNo" 
         || action_event."stagePrimaryNo" || action_event."stageSecNo") = p_rrn;
$$ LANGUAGE sql;

來驗證一下剛才的函式有建立成功
我們給一個參數查詢

select * from getenemy_byevent('000000000401')

OK!有查詢到了

6
我們再回到A組件中
因為剛才有建立取得敵人資訊的函式了
我們此時需要建立一個監聽msg的事件 這邊要用到watch屬性

watch(  () => props.msg, async (newVal) => {
  if (newVal) {
		const rrn = `${newVal.actionNo}${newVal.eventNo}${newVal.stagePrimaryNo}${newVal.stageSecNo}`;
		const { data, error } = await supabase
		.rpc("getenemy_byevent", { p_rrn: rrn}) 

		if (error) {
		console.error(error);
		} else {
		result.value = data;
		}
	} 
  }); 

當msg有變動的時候,會去連Supabase重新取得敵人資訊
最後,看一下輸出結果
下一篇會把這些資料套在template建立的區塊中

備註
1
Supabase建立Function時
注意名稱全部使用小寫

關於Watch監聽器
因為可能有時候會需要更改DOM或異步操作(像上述的讀取資料庫)
就需要使用watch實現,而非使用computed

這邊Watch第一個參數需要的是監聽對象的ref
也就是說,它不接受props.msg
而是要 用getter函數 這種() => props.msg

官方文件對於watch監聽器的說明有一個段落提到
因為下面這範例的obj不是ref
也就是說 它只會監聽到「0」
而沒有辦法監聽到後續的變化

const obj = reactive({ count: 0 })

// 錯誤,因為 watch() 得到的參數是一個 number
watch(obj.count, (count) => {
  console.log(`Count is: ${count}`)
})

所以它的文件中,在下面補充了說明

// 提供一個 getter 函數
watch(
  () => obj.count,
  (count) => {
    console.log(`Count is: ${count}`)
  }
)

上一篇
遊戲活動關卡查詢網站Day14-顯示副本資訊2(Vue:Props)
下一篇
遊戲活動關卡查詢網站Day16-敵人資訊2(JSON架構轉換)
系列文
遊戲活動關卡查詢網站23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言