2025-04-23

Vue.js 狀況:onMount 更新變數後,畫面沒有進行變動

狀況

以下是我的 Vue code

<script setup>
let menuTabs = ref([
	{name: "會員", checked: false},
	{name: "客戶", checked: false},
	{name: "站點", checked: false},
])



let selectedMember = ref({name: null, id: null})
let selectedCustomer = ref({name: null, id: null})
let selectedStation = ref({name: null, id: null})

/** 根據當前選擇的 tab 來決定顯示的內容 */
let selectedData = computed(function(){
	if(menuTabs.value[0].checked){
		return selectedMember.value
	}
	if(menuTabs.value[1].checked){
		return selectedCustomer.value
	}
	if(menuTabs.value[2].checked){
		return selectedStation.value
	}
	return {name: null, id: null}
})

/** 切換 menu tab */
function changeMenuTab(index){
	for(let i = 0; i < menuTabs.value.length; i++){
		menuTabs.value[i].checked = i == index
	}
}

</script>
<template>
	<div class="tabs">
  		<div role="tablist" aria-label="Sample Tabs">
			<button v-for = "(tab, index) in menuTabs"
				role="tab"
				:aria-selected="tab.checked"
				:aria-controls="`panel-${index}`"
				:id="`tab-${index}`"
				:tabindex="tab.checked ? 0 : -1" 
				@click="changeMenuTab(index)"
				v-text="tab.name"/>
		</div>
	</div>


	<div class="tab-content">
		<div>
			{{selectedData.name}}
			<template v-if="!!selectedData.id">
				({{selectedData.id}})
			</template>
		</div>


		<div v-for = "(tab, index) in menuTabs"
			role="tabpanel"
			:aria-labelledby="`tab-${index}`"
			:id="`panel-${index}`"
			:aria-hidden="!tab.checked"
			:tabindex="0"
			:hidden="!tab.checked">
			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus, congue vel laoreet ac, dictum vitae odio.
		</div>
	</div>
</template>

我現在要做的,是當我進來此頁時,確認 storage (以 session storage 為例)

在 storage 中有資料的話,根據資料,顯示會員/客戶/站點的資料

例如

function loadSessionStorageData(){
	let data = JSON.parse(sessionStorage.getItem("data")) as {type: string, name: string: id: string}
	if(data == null){
		return
	}
	for(let i = 0; i < menuTabs.value.length; i++){
		menuTabs.value[i].checked = menuTabs.value[i].name == data.type

		if(menuTabs.value[i].checked){
			switch(data.type){
				case "會員":
					selectedMember.value.name = data.name
					selectedMember.value.id = data.id
					break
				case "客戶":
					selectedCustomer.value.name = data.name
					selectedCustomer.value.id = data.id
					break
				case "站點":
					selectedStation.value.name = data.name
					selectedStation.value.id = data.id
					break
			}
		}
	}
}
onMount(function(){
	loadSessionStorageData()
})

然而,實際執行下,事情並未照我預期的發展

進入該頁後,menuTabsselectedMemberselectedCustomerselectedStationselectedData確實有照我程式所寫的那樣賦值。

但是畫面上,並沒有填入selectedData更新後的內容,但要是我點了 menu tab,又會正常顯示

例如我 session storage 的值是 {"type":"會員","name":"司馬太郎","id":"72C8C419"}

理論上,進來畫面的話,要顯示為

<div class="tab-content">
	<div>司馬太郎(72C8C419)</div>

	<div role="tabpanel" aria-labelledby="tab-0" id="panel-0" aria-hidden="false" tabindex="0"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus, congue vel laoreet ac, dictum vitae odio. </div>
	<!-- 下略 -->
</div>

但是實際上沒顯示

但如果我點下 <button role="tab" aria-selected="false" aria-controls="panel-0" id="tab-0" tabindex="-1">會員</button> 這個 tab 後,會員名稱又會出現了

解決辦法

要解決的話,要使用 nextTick()

loadSessionStorageData 改成如下

function loadSessionStorageData(){
	let data = JSON.parse(sessionStorage.getItem("data")) as {type: string, name: string: id: string}
	if(data == null){
		return
	}
	nuxtTick()
		.then(function(){
			for(let i = 0; i < menuTabs.value.length; i++){
				menuTabs.value[i].checked = menuTabs.value[i].name == data.type

				if(menuTabs.value[i].checked){
					switch(data.type){
						case "會員":
							selectedMember.value.name = data.name
							selectedMember.value.id = data.id
							break
						case "客戶":
							selectedCustomer.value.name = data.name
							selectedCustomer.value.id = data.id
							break
						case "站點":
							selectedStation.value.name = data.name
							selectedStation.value.id = data.id
							break
					}
				}
			}
		})
	
}

沒有留言:

張貼留言