Workshop ประจำหัวข้อนี้
ตัวอย่าง Book List
เราจะมาลองใช้ Vue router และ Pinia แบบจัดเต็มมากขึ้น โดย
- เราจะทำ Web ทั้งหมด 3 หน้า คือ BookListView, BookEditView, BookCreateView
├── src
├── App.vue
├── router
│ └── index.js
├── stores
│ └── book.js --> เปลี่ยนเป็น book store
└── views
├── BookListView.vue
└── BookUpdateView.vue
ที่ stores/books.js
- สร้าง books สำหรับเก็บ list หนังสือทั้งหมดอออกมา
- สร้าง method มาทั้งหมด 3 อันคือ
addBook
สำหรับเพ่ิมหนังสือupdateBook
สำหรับอัพเดทหนังสือremoveBook
สำหรับลบหนังสือ
import { defineStore } from 'pinia'
export const useBookStore = defineStore('book', {
state: () => ({
books: []
}),
actions: {
addBook (book) {
this.books.push(book)
},
updateBook (book, index) {
this.books.splice(index, 1, book)
},
removeBook (index) {
this.books.splice(index, 1)
}
}
})
ที่ routers/index.js
- สร้างหน้ามาทั้งหมด 3 หน้าคือ
- หน้า list หนังสือ (ใช้ BookListView)
- หน้า add หนังสือ (ใช้ BookUpdateView)
- หน้า edit หนังสือ (ใช้ BookUpdateView ตัวเดียวกัน)
import { createRouter, createWebHistory } from 'vue-router'
import BookListView from '../views/BookListView.vue'
import BookUpdateView from '../views/BookUpdateView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'book-list-view',
component: BookListView
},
{
path: '/book/create',
name: 'book-create-view',
component: BookUpdateView
},
{
path: '/book/update/:id',
name: 'book-update-view',
component: BookUpdateView
}
]
})
export default router
ที่ views/BookListView.vue
- หน้าหลักสำหรับแสดงหนังสือทั้งหมดออกมา
- ในหน้านี้จะเพิ่มปุ่มเพื่อไปหน้า add book
- และใน list แต่ละหนังสือจะเพิ่ม edit book (สำหรับแก้ไขข้อมูล) และ remove book (สำหรับลบหนังสือ)
<script setup>
import { RouterLink } from 'vue-router'
import { useBookStore } from '../stores/book'
const bookStore = useBookStore()
</script>
<template>
<div>
Book List view
<RouterLink :to="{ name: 'book-create-view' }">
<button>Add new book</button>
</RouterLink>
<ul>
<li v-for="(book, index) in bookStore.books" :key="book">
({{ index }}) {{ book.name }} by {{ book.author }}
<RouterLink :to="{ name: 'book-update-view', params: { id: index } }">
<button>Edit</button>
</RouterLink>
<button @click="bookStore.removeBook(index)">Delete</button>
</li>
</ul>
</div>
</template>
ที่ views/BookUpdateView.vue
- ที่หน้านี้เราจะทำ 2 อย ่างคือ เพิ่มหนังสือ (addBook) และ อัพเดทข้อมูลหนังสือ (updateBook)
- โดยเราจะแยกออกด้วยตัวแปร mode โดย check จาก route name ว่า route name ชื่อว่าอะไร
<script setup>
import { onMounted, ref, reactive } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useBookStore } from '../stores/book'
const bookStore = useBookStore()
const route = useRoute()
const router = useRouter()
const mode = ref('')
const bookData = reactive({
name: '',
author: ''
})
const bookIndex = ref(-1)
const updateBook = () => {
if (mode.value === 'create') {
bookStore.addBook(bookData)
} else {
bookStore.updateBook(bookData, bookIndex.value)
}
router.push({ name: 'book-list-view' })
}
onMounted(() => {
if (route.params.id) {
bookIndex.value = parseInt(route.params.id)
const cBookData = bookStore.books[bookIndex.value]
bookData.name = cBookData.name
bookData.author = cBookData.author
}
if (route.name === 'book-create-view') {
mode.value = 'create'
} else {
mode.value = 'update'
}
})
</script>
<template>
<div>
Book {{ mode }} view
<div>
<div>Book Name</div>
<input type="text" v-model="bookData.name">
<div>Book Author</div>
<input type="text" v-model="bookData.author">
<div class="action">
<button @click="updateBook()">
{{ mode }} book
</button>
</div>
</div>
</div>
</template>
<style scoped>
.action {
margin-top: 10px;
}
</style>
และนี่คือผลลัพธ์ทั้งหมดของ workshop