因為想留著昨天完成的撲克牌連連看,預計將不同遊戲的頁面可以做保留並切換,
所以我打算在做牌堆之前,首先應該要了解Vue3在路由頁面的實作是如何切換頁面。
接下來步驟我是參考『直接使用npm create vue@latest
指令產生預設攜帶有用Vue Router
專案的檔案架構』
下去調整的,所以步驟草率請敬請見諒。
Vue Router
npm install vue-router@4
views
和router
views
資料夾底下新增兩個頁面檔Game1View.vue
和HomeView.vue
src
├─App.vue
├─main.js
├─views
| ├─Game1View.vue # 撲克連連看
| └─HomeView.vue # 首頁
├─utils
| ├─constants.js
| └─poker-helper.js
├─router
| └─index.js
├─components
| ├─Card.vue
| ├─FoxyHeader.vue
| ├─GameBoard.vue
| 略...
如果想知道是怎麼產生樹狀目錄,我是在src目錄下執行
npx treer -e ./result.txt
便會
將樹狀結構寫到當前的result.txt
文件中
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/game1',
name: 'game1',
// Lazy Loading
component: () => import('../views/Game1View.vue')
}
]
})
export default router
App.vue
修改成以下結構,RouterView
就是渲染對應路由的元件,RouterLink
則是像<a>
的連結會修改網址的對應路由,只是不會重新整理整個網頁,而是動態載入去切換部分畫面、網址。// App.vue
<script setup>
import { RouterView, RouterLink } from 'vue-router';
</script>
<template>
<header>
<nav>
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/game1">撲克牌連連看</RouterLink>
</nav>
</header>
<RouterView />
</template>
如果需要當前路由對應到對應連結時自動套用特定class的話,不一定要在每個
<RouterLink>
寫:class=""
去做判斷,只需要在<style>...</style>
中定義class.router-link-active
即可
.router-link-active {
color: #ff4500;
font-weight: bold;
}
main.js
,讓Vue實際掛載第四步驟定義的Router// main.js
import router from './router'
// 略
const app = createApp(App);
app.use(router);
app.mount('#app')
一直以來都是用自訂義的Vue組件都是把props
的方式傳值進去,
但其實還有一個slot
的用法可以把外部組件傳進去。
slot用法非常簡單,只需要在元件中添加<slot>...</slot>
,
以當前專案舉例,因為之後<FoxyHeader>
可能會添加在每個遊戲上方,因為每個遊戲的標題都不相同,所以在此改用slot
做調整。
// FoxyHeader.vue
<template>
<header>
<div>
<!-- 以下slot就是標題位置 -->
<slot>No child component passed in</slot>
</div>
<img src="../assets/imgs/foxy01.jpg" class="foxyHead" />
</header>
</template>
然後在<FoxyHeader>
和</FoxyHeader>
中間添加想要的文字或HTML組件,就填充到對應的slot
位置,如果沒填充才會顯示上方寫的No child component passed in。
// Game1view.vue
<template setup>
<main>
<FoxyHeader>撲克牌連連看</FoxyHeader>
<GameBoard />
</main>
</template>
將牌桌<GameBoard>
改用slot,控制牌桌上卡片排序的職責也拆成一個新元件<CardRow>
,
將撲克牌連連看的內容都移入全都移入Game1View.vue
,所以後者的樣板變成以下結構:
// Game1View.vue
<template setup>
<main>
<FoxyHeader>撲克牌連連看</FoxyHeader>
<button style="font-size: 1.5rem;" @click="resetGame">重置</button>
<div style="font-size:1.5rem;">
<div>當前分數: {{ gameScore }}</div>
<div>時間經過: {{ timerFormat }}</div>
</div>
<GameBoard>
<CardRow>
<Card v-for="card in boardCards" :key="card.value" :value="card.value" :isOpen="card.isOpen"
:isDone="card.isDone" @poker-flip="toggleFlip" />
</CardRow>
</GameBoard>
</main>
</template>
小結
本來想先做牌堆沒做成,倒是學習如何應用Vue Router
和slot
程式碼: https://github.com/kabuto412rock/ithelp-pokergame/tree/day05
參考