Skip to main content

แนะนำ Router และ Pinia คืออะไร ?

vue-router-pinia สามารถดู video ของหัวข้อนี้ก่อนได้ ดู video

เมื่อ project ใหญ่ขึ้น เราควรจัดการมันยังไงดี

เมื่อ project เราเริ่มใหญ่ขึ้น (อย่างที่เห็นอย่างตัวอย่าง code ในหน้า profile ของ session ก่อน) จะเห็นว่าถ้าเกิดเริ่มมีหลายหน้ามากขึ้น code ก็จะเริ่มสับซ้อนมากขึ้น รวมถึงหากต้องมีการ communication ระหว่างหลายๆหน้า จำเป็นที่จะต้องมีตัวกลางในการสื่อสารมากขึ้น

เราถึงต้องการ Router (สำหรับการแบ่งหน้า) และ Pinia (State management กลาง) ออกมา เราจะมาทำความรู้จักกับทั้ง 2 ตัวก่อนว่ามันคืออะไร

Vue Router คืออะไร ?

Document ต้นฉบับ: https://router.vuejs.org/guide/

Vue router คือ ตัวที่ช่วยสำหรับการจัดการ path กับ Vue component

  • Vue router มีส่วนช่วยในการ map แต่ละหน้ากับ component เข้าด้วยกัน และสามารถจัดการเรื่องของการ render ให้

นี่คือตัวอย่าง code ของ Router

<script src="https://unpkg.com/vue@3"></script>
<script src="https://unpkg.com/vue-router@4"></script>

<div id="app">
<h1>Hello App!</h1>
<p>
<router-link to="/">Go to Home</router-link>
<router-link to="/about">Go to About</router-link>
</p>
<router-view></router-view>
</div>

แล้ว Pinia ละ คืออะไร ?

Document ต้นฉบับ: https://pinia.vuejs.org/introduction.html

Pinia คือตัว store library สำหรับจัดการ state ของ Vue ที่อนุญาตให้แชร์ state กันระหว่าง components, pages ในแต่ละส่วนของ Vue

ถ้าเทียบกับการเอา state ออกมาอยู่ที่ระดับ global state แทนและสามารถเรียกใช้กับ components, pages อื่นๆได้

นี่คือตัวอย่างของ code ของ Pinia

App.vue

<script setup>
import { useCounterStore } from '@/stores/counter'

const counter = useCounterStore()

counter.count++
// with autocompletion ✨
counter.$patch({ count: counter.count + 1 })
// or using an action instead
counter.increment()
</script>

<template>
<!-- Access the state directly from the store -->
<div>Current Count: {{ counter.count }}</div>
</template>

counter.js สำหรับเก็บ state - เปรียบเหมือนสร้าง state ตัวกลางแทน

export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function increment() {
count.value++
}

return { count, increment }
})

ทำไมเราถึงต้องรู้จัก Router และ Pinia ?

เหตุผลที่เราควรรู้จัก 2 ตัวนี้คือ

เว็บไซต์เรามีหลายหน้า Router และ Pinia มีส่วนช่วยทำให้การจัดการหน้าเว็บหลายหน้าจัดการได้ง่ายขึ้น สามารถจัดการ navigtion ในแต่ละ path และสามารถ share state ระหว่าง Component ออกมาจากกันได้ง่ายขึ้น

ส่วน Pinia นั่น ต้องยอมรับว่า ถ้าใช้เป็น Composition API style code จะมีความใกล้เคียงกันมาก (ใกล้กว่ากับ Vuex ซึ่งจริงๆ Vuex ก็เป็น store state management ที่มีโจทย์เดียวกันกับ Pinia เช่นกัน)

เราจะเริ่ม setup project กันใหม่

รอบนี้เราจะเปลี่่ยนมาใช้ Vue CLI ในการ setup แทน (จะเปลี่ยนจากการใช้ Vite ตรงๆมาเป็นใช้ผ่าน Vue CLI แทน แต่ผลลัพธ์ออกมาก็จะได้ Vite เป็นตัว run project ตามเดิม)

npm create vue@latest

แล้วเลือกใช้ 2 ตัวคือ Router กับ Pinia

✔ Project name: … <your-project-name>
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes

ภาพตัวอย่างการเลือก (เลือก Yes, No ตามนี้ก่อนได้)

intro-01

เสร็จแล้วเราจะได้ structure project ออกมาประมาณนี้

├── README.md
├── index.html
├── package.json
├── public
│   └── favicon.ico
├── src
│   ├── App.vue --> Root component เหมือนเดิม
│   ├── assets
│   │   ├── base.css
│   │   ├── logo.svg
│   │   └── main.css
│   ├── components --> folder component เหมือนเดิม
│   │   ├── HelloWorld.vue
│   │   ├── TheWelcome.vue
│   │   ├── WelcomeItem.vue
│   │   └── icons
│   │   ├── IconCommunity.vue
│   │   ├── IconDocumentation.vue
│   │   ├── IconEcosystem.vue
│   │   ├── IconSupport.vue
│   │   └── IconTooling.vue
│   ├── main.js --> file เริ่มต้นเหมือนเดิม
│   ├── router --> folder ของ router
│   │   └── index.js
│   ├── stores --> folder ของ state management pinia
│   │   └── counter.js
│   └── views
│   ├── AboutView.vue
│   └── HomeView.vue
└── vite.config.js

run ตามที่มันบอกได้เลย

npm install
npm run dev

จะได้ผลลัพธ์ประมาณนี้ออกมา

intro-02

และเราก็จะพร้อมลุยกันต่อ

เกร็ด: เหตุผลที่ผมใช้พวก CLI เป็นตัวเริ่มต้น project เพื่อให้เราไม่ต้องเสียเวลามานั่งคิดว่าเราจะต้องเริ่มต้นวาง project ยังไงได้ (เราจะเรียกว่าได้ boilerplate project มา)