วิธีสร้างโปรแกรมจัดการเพลงด้วย Nuxt.js และ Express.js
เผยแพร่แล้ว: 2022-03-10การจัดการทรัพย์สินสื่อดิจิทัล เช่น เสียงและวิดีโอในแอปพลิเคชันของคุณอาจเป็นเรื่องยุ่งยาก เนื่องจากข้อควรพิจารณาที่ต้องทำในฝั่งเซิร์ฟเวอร์ อย่างไรก็ตาม เราสามารถใช้ไลบรารีต่างๆ เช่น Multer และ Express.js เพื่อทำให้เวิร์กโฟลว์ของเราในแบ็กเอนด์ง่ายขึ้นในขณะที่ใช้ Nuxt.js (เฟรมเวิร์ก Vue) เพื่อสร้างการโต้ตอบส่วนหน้า
เมื่อใดก็ตามที่เว็บไคลเอ็นต์อัปโหลดไฟล์ไปยังเซิร์ฟเวอร์ โดยทั่วไปแล้ว ไฟล์จะถูกส่งผ่านแบบฟอร์มและเข้ารหัสเป็น multipart/form-data
Multer
เป็นมิดเดิลแวร์สำหรับ Express.js และ Node.js ที่ทำให้ง่ายต่อการจัดการสิ่งที่เรียกว่า multipart/form-data
เมื่อใดก็ตามที่ผู้ใช้ของคุณอัปโหลดไฟล์ ในบทช่วยสอนนี้ ฉันจะอธิบายวิธีสร้างแอปตัวจัดการเพลงโดยใช้ Express.js กับ Multer เพื่ออัปโหลดเพลงและ Nuxt.js (เฟรมเวิร์ก Vue) สำหรับส่วนหน้าของเรา
ข้อกำหนดเบื้องต้น
- ความคุ้นเคยกับ HTML, CSS และ JavaScript (ES6+);
- ติดตั้ง Node.js, npm และ MongoDB บนเครื่องพัฒนาของคุณ
- รหัส VS หรือโปรแกรมแก้ไขรหัสใด ๆ ที่คุณเลือก
- ความรู้พื้นฐานเกี่ยวกับ Express.js
การสร้างบริการแบ็คเอนด์
เริ่มต้นด้วยการสร้างไดเร็กทอรีสำหรับโครงการของเราโดยไปที่ไดเร็กทอรีและออก npm init -y
บนเทอร์มินัลของคุณเพื่อสร้างไฟล์ package.json ที่จัดการการพึ่งพาทั้งหมดสำหรับแอปพลิเคชันของเรา
mkdir serverside && cd serverside npm init -y
ถัดไป ติดตั้ง multer
, express
และการอ้างอิงอื่นๆ ที่จำเป็นสำหรับ Bootstrap แอป Express.js
npm install express multer nodemon mongoose cors morgan body-parser --save
ถัดไป สร้างไฟล์ index.js :
touch index.js
จากนั้นในไฟล์ index.js เราจะเริ่มต้นโมดูลทั้งหมด สร้างแอป Express.js และสร้างเซิร์ฟเวอร์สำหรับเชื่อมต่อกับเบราว์เซอร์:
const express = require("express"); const PORT = process.env.PORT || 4000; const morgan = require("morgan"); const cors = require("cors"); const bodyParser = require("body-parser"); const mongoose = require("mongoose"); const config = require("./config/db"); const app = express(); //configure database and mongoose mongoose.set("useCreateIndex", true); mongoose .connect(config.database, { useNewUrlParser: true }) .then(() => { console.log("Database is connected"); }) .catch(err => { console.log({ database_error: err }); }); // db configuaration ends here //registering cors app.use(cors()); //configure body parser app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); //configure body-parser ends here app.use(morgan("dev")); // configire morgan // define first route app.get("/", (req, res) => { res.json("Hola MEVN devs...Assemble"); }); app.listen(PORT, () => { console.log(`App is running on ${PORT}`); });
ก่อนอื่น เรานำ Express.js เข้ามาในโปรเจ็กต์ จากนั้นจึงกำหนดพอร์ตที่แอปพลิเคชันของเราจะใช้งาน ต่อไป เรานำ body-parser
, morgan
, mongoose
และ cors
dependencies
จากนั้นเราบันทึกอินสแตนซ์ด่วนในตัวแปรที่เรียกว่า app
เราสามารถใช้อินสแตนซ์ของ app
เพื่อกำหนดค่ามิดเดิลแวร์ในแอปพลิเคชันของเราได้เช่นเดียวกับที่เรากำหนดค่า cors
ของคอร์ เรายังใช้อินสแตนซ์ของ app
เพื่อตั้งค่าเส้นทางรูทที่จะทำงานในพอร์ตที่เรากำหนด
ตอนนี้มาสร้างโฟลเดอร์ /config
สำหรับฐานข้อมูล config
และ multer
config:
mkdir config and cd config touch multer.js && touch db.js
จากนั้นเปิด config/db.js และเพิ่มรหัสต่อไปนี้เพื่อกำหนดค่าฐานข้อมูลของเรา:
module.exports = { database: "mongodb://localhost:27017/", secret: "password" };
(นี่คือวัตถุที่เก็บ URL ฐานข้อมูลและความลับของฐานข้อมูล)
การเรียกใช้ nodemon
และการนำทางไปยัง localhost:4000
บนเบราว์เซอร์ของคุณควรให้ข้อความนี้แก่คุณ:
"Hola MEVN devs...Assemble"
นอกจากนี้ นี่คือสิ่งที่เทอร์มินัลของคุณควรมีลักษณะดังนี้:
การตั้งค่าโมเดล เส้นทาง และตัวควบคุม
มาตั้งค่าโครงสร้างไฟล์กันโดยพิมพ์ดังนี้
mkdir api && cd api mkdir model && cd model && touch Music.js cd .. mkdir controller && cd controller && touch musicController.js cd .. mkdir routes && cd routes && touch music.js
ในเทอร์มินัลของเรา เราใช้ mkdir
เพื่อสร้างไดเร็กทอรีใหม่ จากนั้น cd
เพื่อย้ายไปยังไดเร็กทอรี ดังนั้นเราจึงเริ่มต้นด้วยการสร้างไดเร็กทอรีที่เรียกว่า api
แล้วย้ายไปยังไดเร็กทอรี api
คำสั่ง touch
ใช้สำหรับสร้างไฟล์ใหม่ภายในไดเร็กทอรีโดยใช้เทอร์มินัล ในขณะที่คำสั่ง cd
ใช้เพื่อย้ายออกจากไดเร็กทอรี
ตอนนี้ ไปที่ไฟล์ api/model/Music.js เพื่อสร้างสคีมาเพลง โมเดลคือคลาสที่เราสร้างเอกสาร ในกรณีนี้ เอกสารแต่ละฉบับจะเป็นเพลงที่มีคุณสมบัติและลักษณะการทำงานตามที่ประกาศไว้ในสคีมาของเรา:
let mongoose = require("mongoose"); let musicSchema = mongoose.Schema({ title: { type: String, required: true }, music: { type: Object, required: true }, artist: { type: String, required: true }, created: { type: Date, default: Date.now() } }); let Music = mongoose.model("Music", musicSchema); module.exports = Music;
ไปที่ config/multer
เพื่อกำหนดค่า Multer:
let multer = require("multer"); const path = require("path"); const storage = multer.diskStorage({ destination: (req, res, cb) => { cb(null, "./uploads"); }, filename: (req, file, cb) => { cb(null, new Date().toISOString() + file.originalname); } }); const fileFilter = (req, file, cb) => { if ( file.mimetype === "audio/mpeg" || file.mimetype === "audio/wave" || file.mimetype === "audio/wav" || file.mimetype === "audio/mp3" ) { cb(null, true); } else { cb(null, false); } }; exports.upload = multer({ storage: storage, limits: { fileSize: 1024 * 1024 * 5 }, fileFilter: fileFilter });
ในไฟล์ multer.js เราเริ่มต้นด้วยการตั้งค่าโฟลเดอร์ที่จะอัปโหลดไฟล์เพลงที่อัปโหลดทั้งหมด เราจำเป็นต้องทำให้ไฟล์นี้เป็นสแตติกโดยกำหนดในไฟล์ index.js :
app.use('/uploads', express.static('uploads'));
หลังจากนั้น เราเขียนเครื่องมือตรวจสอบอย่างง่ายที่จะตรวจสอบประเภทไฟล์ mime ก่อนอัปโหลด จากนั้นเราจะกำหนดอินสแตนซ์ multer
โดยเพิ่มตำแหน่งที่เก็บข้อมูล ขีดจำกัดของแต่ละไฟล์ และตัวตรวจสอบความถูกต้องที่เราสร้างขึ้น
สร้างเส้นทางที่จำเป็น
มาสร้างเส้นทางของเรากัน ด้านล่างนี้คือรายการปลายทางที่เราจะสร้าง
HTTP POST /music | เพิ่มเพลงใหม่ |
HTTP GET /music | รับทุกเพลง |
HTTP DELETE /music/:blogId | ลบเพลง |
เริ่มต้นด้วยการสร้างเส้นทางบล็อก ตรงไปที่ api/routes/music.js และเขียนโค้ดต่อไปนี้:
const express = require("express"); const router = express.Router(); const musicController = require("../controller/musicController"); const upload = require("../../config/multer"); router.get("/", musicController.getAllMusics); router.post("/", upload.upload.single("music"), musicController.addNewMusic); router.delete("/:musicId", musicController.deleteMusic); module.exports = router;
หมายเหตุ : ตอนนี้เมื่อใดก็ตามที่เราทำการ ร้องขอไป get
/ /music
เส้นทางเรียก ฟังก์ชัน getAllMusic
ที่อยู่ในไฟล์ 'controllers'
ไปที่ api/controllers/musicController
เพื่อกำหนดคอนโทรลเลอร์ เราเริ่มต้นด้วยการเขียนฟังก์ชันเพื่อรับเพลงทั้งหมดในฐานข้อมูลของเราโดยใช้เมธอด mongoose db.collection.find
ซึ่งจะส่งคืนรายการทั้งหมดในคอลเล็กชันนั้น
หลังจากทำอย่างนั้น เราเขียนฟังก์ชันอื่นที่จะสร้างเพลงใหม่ในฐานข้อมูล เราจำเป็นต้องสร้างอินสแตนซ์เพลงใหม่โดยใช้คำหลัก new
แล้วกำหนดวัตถุเพลง หลังจากนี้เราจะใช้วิธี save
พังพอนเพื่อเพิ่มเพลงใหม่ลงในฐานข้อมูล
ในการลบเพลง เราจำเป็นต้องใช้วิธีการ remove
พังพอน โดยเพียงแค่ส่ง ID เพลงเป็นพารามิเตอร์ในอินสแตนซ์การ remove
ส่งผลให้พังพอนมองเข้าไปในคอลเลคชันเพลงที่มี ID นั้น ๆ แล้วลบออกจากคอลเล็กชันนั้น
let mongoose = require("mongoose"); const Music = require("../model/Music"); exports.getAllMusics = async (req, res) => { try { let music = await Music.find(); res.status(200).json(music); } catch (err) { res.status(500).json(err); } }; exports.addNewMusic = async (req, res) => { try { const music = new Music({ title:req.body.title, artist:req.body.artist, music:req.file }); let newMusic = await music.save(); res.status(200).json({ data: newMusic }); } catch (err) { res.status(500).json({ error: err }); } }; exports.deleteMusic = async (req, res) => { try { const id = req.params.musicId; let result = await Music.remove({ _id: id }); res.status(200).json(result); } catch (err) { res.status(500).json(err); } };
สุดท้ายแต่ไม่ท้ายสุด เพื่อทดสอบเส้นทาง เราจำเป็นต้องลงทะเบียนเส้นทางเพลงในไฟล์ index.js ของเรา:
const userRoutes = require("./api/user/route/user"); //bring in our user routes app.use("/user", userRoutes);
การทดสอบจุดสิ้นสุด
ในการทดสอบปลายทาง เราจะใช้ POSTMAN
เพิ่มเพลงใหม่
หากต้องการทดสอบฟังก์ชัน Add Music
ให้ตั้งค่าวิธีการของคำขอโดยคลิกที่เมนูรายการแบบเลื่อนลง หลังจากทำเช่นนี้ ให้พิมพ์ URL ของปลายทาง จากนั้นคลิกที่แท็บเนื้อหาเพื่อเลือกวิธีที่คุณต้องการส่งข้อมูลของคุณ (ในกรณีของเรา เราจะใช้วิธี form-data)
ดังนั้นคลิกที่ form-data และตั้งค่ารหัสโมเดลของคุณ ในขณะที่คุณตั้งค่า ให้ตั้งค่าคีย์บางค่าตามที่แสดงในภาพด้านล่าง:
หลังจากทำเช่นนี้ ให้คลิกที่ 'ส่ง' เพื่อส่งคำขอ
รายชื่อเพลงทั้งหมด
ในการแสดงรายการเพลงทั้งหมดในฐานข้อมูลของเรา เราต้องพิมพ์ URL ปลายทางในส่วน URL ที่ให้ไว้ หลังจากทำเช่นนี้ ให้คลิกที่ปุ่ม 'ส่ง' เพื่อทำการร้องขอ
การลบเพลง
ในการลบเพลง เราต้องส่ง music id
เป็นพารามิเตอร์
แค่นั้นแหละ!
การสร้างส่วนหน้า
สำหรับส่วนหน้า เราจะใช้ Vue framework: Nuxt.js
“Nuxt เป็นเฟรมเวิร์กแบบโปรเกรสซีฟที่ใช้ Vue.js เพื่อสร้างเว็บแอปพลิเคชันที่ทันสมัย มันขึ้นอยู่กับไลบรารีอย่างเป็นทางการของ Vue.js (vue, vue-router และ vuex) และเครื่องมือการพัฒนาที่ทรงพลัง (webpack, Babel และ PostCSS)”
— คู่มือ NuxtJS
ในการสร้างแอปพลิเคชัน Nuxt.js ใหม่ ให้เปิดเทอร์มินัลของคุณและพิมพ์ดังต่อไปนี้ (โดยใช้ musicapp
เป็นชื่อแอปที่เราจะสร้าง):
$ npx create-nuxt-app musicapp
ในระหว่างขั้นตอนการติดตั้ง เราจะถามคำถามเกี่ยวกับการตั้งค่าโครงการ:
Project name | musicapp |
project description | แอพจัดการเพลงอย่างง่าย |
Author name | <ชื่อของคุณ> |
Package manager | npm |
UI framework | Bootstrap วิว |
custom ui framework | ไม่มี |
Nuxt modules | Axios,pwa (ใช้แป้นเว้นวรรคบนแป้นพิมพ์เพื่อเลือกรายการ) |
Linting tool | สวยขึ้น |
test framework | ไม่มี |
Rendering Mode | สากล (SSR) |
development tool | Jsonconfig.json |
หลังจากเลือกทั้งหมดนี้แล้ว เราต้องรออีกสักพักกว่าจะตั้งโปรเจ็กต์ได้ เมื่อพร้อมแล้ว ให้ย้ายไปที่โฟลเดอร์ /project
และให้บริการโครงการดังนี้:
cd musicapp && npm run dev
เปิดโปรเจ็กต์ในตัวแก้ไขโค้ดใดๆ ที่คุณเลือก จากนั้นเปิดโปรเจ็กต์ในเบราว์เซอร์โดยเข้าถึง localhost:3000
การกำหนดค่า Axios
เราจะใช้ axios
เพื่อส่งคำขอ HTTP ไปยังเซิร์ฟเวอร์ส่วนหลังของเรา Axios ได้รับการติดตั้งแล้วในโปรเจ็กต์ของเรา ดังนั้นเราแค่ต้องกำหนดค่า baseURL
- ไปยังเซิร์ฟเวอร์แบ็กเอนด์ของเรา
ในการดำเนินการนี้ ให้เปิดไฟล์ nuxt.config.js ในไดเร็กทอรี root
และเพิ่ม baseURL
ในอ็อบเจ็กต์ axios
axios: { baseURL:'https://localhost:4000' },
การสร้างผู้จัดการเพลง
การตั้งค่า UI
เริ่มต้นด้วยการล้าง UI เปิดไฟล์ pages/index.vue และลบโค้ดทั้งหมดที่มีดังต่อไปนี้:
<template> <div>Hello</div> </template>
หลังจากทำเช่นนี้ คุณควรจะสามารถเห็น "สวัสดี" ในเบราว์เซอร์เท่านั้น
ในไดเร็กทอรี root
ให้สร้างโฟลเดอร์ /partials
ภายในโฟลเดอร์ /partials
ให้สร้างไฟล์ navbar.vue และเพิ่มโค้ดต่อไปนี้:
<template> <header> <nav class="navbar navbar-expand-lg navbar-light bg-info"> <div class="container"> <a class="navbar-brand" href="#">Music App</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation" > <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse justify-content-end"> <ul class="navbar-nav"> <li class="nav-item active"> <a class="nav-link" href="#">Player</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Manager</a> </li> </ul> </div> </div> </nav> </header> </template> <style scoped> .nav-link, .navbar-brand { color: #ffff !important; } </style>
หมายเหตุ : เราจะใช้ส่วนประกอบเพื่อนำทางผ่านหน้าต่างๆ ในแอปพลิเคชันของเรา นี่เป็นเพียงส่วนประกอบง่ายๆ ที่ประกอบขึ้นจาก Bootstrap navbar
ตรวจสอบเอกสาร Bootstrap อย่างเป็นทางการสำหรับการอ้างอิงเพิ่มเติม
ต่อไป มากำหนดเค้าโครงแบบกำหนดเองสำหรับแอปพลิเคชัน เปิดโฟลเดอร์ /layouts
แทนที่โค้ดในไฟล์ default.vue ด้วยโค้ดด้านล่าง
<template> <div> <navbar /> <nuxt /> </div> </template> <script> import navbar from '@/partial/navbar' export default { components: { navbar } } </script>
เรานำเข้า navbar
ไปยังเลย์เอาต์นี้ หมายความว่าทุกหน้าในแอปพลิเคชันของเราจะมีองค์ประกอบ navbar
นั้นอยู่ในนั้น (นี่จะเป็นส่วนประกอบที่จะติดตั้งส่วนประกอบอื่น ๆ ทั้งหมดในแอปพลิเคชันของเรา)
หลังจากนี้ คุณควรจะสามารถเห็นสิ่งนี้ในเบราว์เซอร์ของคุณ:
ตอนนี้ มาตั้งค่า UI สำหรับผู้จัดการของเรากัน ในการดำเนินการนี้ เราต้องสร้างโฟลเดอร์ /manager
ภายในโฟลเดอร์ส่วนประกอบ แล้วเพิ่มไฟล์ลงในโฟลเดอร์ชื่อ manager.vue
ในไฟล์นี้ เพิ่มรหัสต่อไปนี้:
<template> <section class="mt-5"> <div class="container mb-4"> <div class="row"> <div class="col-md-12"> <div class="card"> <div class="card-body"> <div class="card-title mb-4"> <h4>Add Music</h4> </div> <form> <div class="form-group"> <label for="title">Title</label> <input type="text" class="form-control" /> </div> <div class="form-group"> <label for="artist">Artist</label> <input type="text" class="form-control" /> </div> <div class="form-group"> <label for="artist">Music</label> <div class="custom-file"> <input type="file" class="custom-file-input" /> <label class="custom-file-label" for="customFile">Choose file</label> </div> </div> <div class="form-group"> <button class="btn btn-primary">Submit</button> </div> </form> </div> </div> </div> </div> </div> <div class="container"> <div class="row"> <div class="col-md-12"> <div class="card bg-light p-1 showdow-sm"> <div class="card-title"> <button class="btn btn-info m-3">Add Music</button> </div> <div class="card-body"> <table class="table"> <thead> <tr> <th scope="col">#</th> <th scope="col">Title</th> <th scope="col">Artist</th> <th scope="col">Date created</th> <th scope="col">Action</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>Demo Title</td> <td>Wisdom.vue</td> <td>12/23/13</td> <td> <button class="btn btn-info">Delete</button> </td> </tr> </tbody> </table> </div> </div> </div> </div> </div> </section> </template>
หมายเหตุ : นี่เป็นเพียงเทมเพลต Bootstrap แบบง่ายสำหรับการเพิ่มเพลงลงในแอปพลิเคชันของเรา แบบฟอร์มจะกำหนดเทมเพลตตารางที่จะแสดงรายการเพลงของระบบปฏิบัติการทั้งหมดที่สามารถพบได้ในฐานข้อมูลของเรา
หลังจากกำหนดองค์ประกอบนี้แล้ว เราจำเป็นต้องลงทะเบียนในโฟลเดอร์ /pages
เพื่อเริ่มต้นการกำหนดเส้นทาง
Nuxt.js ไม่มีไฟล์ 'router.js' เช่น Vue.js มันใช้โฟลเดอร์เพจสำหรับการกำหนดเส้นทาง สำหรับรายละเอียดเพิ่มเติม ไปที่เว็บไซต์ Nuxt.js
หากต้องการลงทะเบียนคอมโพเนนต์ ให้สร้างโฟลเดอร์ /manager
ภายในโฟลเดอร์ /pages
และสร้างไฟล์ index.vue จากนั้นวางโค้ดต่อไปนี้ในไฟล์:
<template> <div> <manager /> </div> </template> <script> import manager from '@/components/manager/manager' export default { components: { manager } } </script>
นี่คือองค์ประกอบที่จะแสดงผลในเส้นทางของ pages
ของเรา
หลังจากทำเช่นนี้ ตรงไปที่เบราว์เซอร์ของคุณและไปที่ /manager
– คุณควรเห็นสิ่งนี้:
รายชื่อเพลงทั้งหมด
มาต่อด้วยการสร้างฟังก์ชันที่จะดึงข้อมูลเพลงทั้งหมด ฟังก์ชันนี้จะถูกลงทะเบียนใน hook ของวงจรชีวิตที่สร้างขึ้น ดังนั้นเมื่อใดก็ตามที่สร้างส่วนประกอบขึ้น ฟังก์ชันจะถูกเรียก
เริ่มต้นด้วยการสร้างตัวแปรในอินสแตนซ์ vue
ที่จะเก็บเพลงทั้งหมด:
allmusic = []; musicLoading: false,
จากนั้น กำหนดฟังก์ชัน getAllMusics
และเพิ่มโค้ดต่อไปนี้:
async getAllMusics() { this.musicLoading = true try { let data = await this.$axios.$get('/music') this.allmusic = data this.musicLoading = false } catch (err) { this.musicLoading = false swal('Error', 'Error Fetting Musics', 'error') } }
ถัดไป ลงทะเบียนภายในเบ็ดวงจรชีวิตที่สร้างขึ้น:
created() { this.getAllMusics() }
การส่งออกข้อมูล
ตอนนี้ก็ถึงเวลาที่จะส่งออกเพลงทั้งหมดบนโต๊ะที่เราได้สร้างไว้ก่อนหน้านี้:
<table class="table"> <thead> <tr> <th scope="col">#</th> <th scope="col">Title</th> <th scope="col">Artist</th> <th scope="col">Date created</th> <th scope="col">Action</th> </tr> </thead> <div v-if="musicLoading" class="spinner-border" role="status" > <span class="sr-only">Loading...</span> </div> <tbody v-else> <tr v-for="(music, index) in allmusic" :key="index"> <td>{{ index + 1 }}</td> <td>{{ music.title }}</td> <td>{{ music.artist }}</td> <td>{{ music.created }}</td> <td> <button class="btn btn-info" @click="deleteMusic(music._id)">Delete</button> </td> </tr> </tbody> </table>
จำตารางที่เราสร้างไว้ก่อนหน้านี้หรือไม่? เราจะต้องวนซ้ำการตอบสนองที่เราได้รับจากแบ็กเอนด์เพื่อแสดงรายการเพลงทั้งหมดที่ได้รับกลับมาจากฐานข้อมูล
การเพิ่มเพลง
ในการเพิ่มเพลงใหม่ เราต้องส่งคำขอ HTTP ไปยังเซิร์ฟเวอร์ส่วนหลังพร้อมรายละเอียดเพลง ในการดำเนินการนี้ ให้เริ่มด้วยการแก้ไขแบบฟอร์มและการจัดการการอัปโหลดไฟล์
ในแบบฟอร์ม เราจำเป็นต้องเพิ่มตัวฟัง event
ที่จะรับฟังแบบฟอร์มเมื่อมีการส่ง บนฟิลด์ input
เราเพิ่มโมเดล v-
เพื่อผูกค่ากับฟิลด์อินพุต
<form @submit.prevent="addNewMusic"> <div class="form-group"> <label for="title">Title</label> <input type="text" v-model="musicDetails.title" class="form-control" /> </div> <div class="form-group"> <label for="artist">Artist</label> <input type="text" v-model="musicDetails.artist" class="form-control" /> </div> <div class="form-group"> <label for="artist">Music</label> <div class="custom-file"> <input type="file" ref="file" v-on:change="handleFileUpload()" class="custom-file-input" /> <label class="custom-file-label" for="customFile">Choose file</label> </div> </div> <div class="form-group"> <button class="btn btn-primary" :disabled="isDisabled"> <span class="spinner-border spinner-border-sm" v-if="addLoading" role="status" aria-hidden="true" ></span>Submit </button> </div> </form>
และส่วนสคริปต์ควรมีลักษณะดังนี้:
<script> export default { data() { return { musicDetails: { title: '', artist: '', music: '' }, allmusic = [], musicLoading: false, isValid: false; addLoading: false, } }, computed: { isDisabled: function() { if ( this.musicDetails.title === '' || this.musicDetails.artist === '' || this.musicDetails.music === '' ) { return !this.isValid } } }, methods: { handleFileUpload() { this.musicDetails.music = this.$refs.file.files[0] console.log(this.musicDetails.music.type) }, addNewMusic() { let types = /(\.|\/)(mp3|mp4)$/i if ( types.test(this.musicDetails.music.type) || types.test(this.musicDetails.music.name) ) { console.log('erjkb') } else { alert('Invalid file type') return !this.isValid } } } } </script>
เราจะกำหนดฟังก์ชันที่จะส่งคำขอไปยังบริการแบ็คเอนด์ของเราเพื่อสร้างเพลงใหม่ที่เพิ่มลงในรายการ อีกด้วย. เราจำเป็นต้องเขียนฟังก์ชันการตรวจสอบอย่างง่ายที่จะตรวจสอบประเภทไฟล์เพื่อให้ผู้ใช้สามารถอัปโหลดไฟล์ที่มีนามสกุล .mp3 และ .mp4 เท่านั้น
สิ่งสำคัญคือต้องกำหนดคุณสมบัติที่คำนวณเพื่อให้แน่ใจว่าช่องใส่ของเราไม่ว่างเปล่า เรายังจำเป็นต้องเพิ่มเครื่องมือตรวจสอบอย่างง่ายที่จะทำให้แน่ใจว่าไฟล์ที่เรากำลังพยายามอัปโหลดนั้นเป็นไฟล์เพลงจริงๆ
ดำเนินการต่อโดยแก้ไขฟังก์ชัน addMusic
เพื่อส่งคำขอไปยังบริการแบ็คเอนด์ของเรา แต่ก่อนที่เราจะทำสิ่งนี้ เรามาติดตั้ง sweetalert
ซึ่งจะทำให้เรามีหน้าต่างโมดอลที่ดี ในการดำเนินการนี้ ให้เปิดเทอร์มินัลของคุณและพิมพ์ดังต่อไปนี้:
npm i sweetalert
หลังจากติดตั้งแพ็คเกจแล้ว ให้สร้างไฟล์ sweetalert.js ในโฟลเดอร์ /plugins
และเพิ่มสิ่งนี้:
import Vue from 'vue'; import swal from 'sweetalert'; Vue.prototype.$swal = swal;
จากนั้นลงทะเบียนปลั๊กอินในไฟล์ nuxt.config.js ภายในปลั๊กอินอินสแตนซ์ดังนี้:
plugins: [ { src: '~/plugins/sweetalert' } ],
ตอนนี้เราได้กำหนดค่า sweetalert
ในแอปพลิเคชันของเราเรียบร้อยแล้ว ดังนั้นเราจึงสามารถดำเนินการต่อและแก้ไขฟังก์ชัน addmusic
เป็นดังนี้:
addNewMusic() { let types = /(\.|\/)(mp3|mp4)$/i if ( types.test(this.musicDetails.music.type) || types.test(this.musicDetails.music.name) ) { let formData = new FormData() formData.append('title', this.musicDetails.title) formData.append('artist', this.musicDetails.artist) formData.append('music', this.musicDetails.music) this.addLoading = true this.$axios .$post('/music', formData) .then(response => { console.log(response) this.addLoading = false this.musicDetails = {} this.getAllMusics() // we will create this function later swal('Success', 'New Music Added', 'success') }) .catch(err => { this.addLoading = false swal('Error', 'Something Went wrong', 'error') console.log(err) }) } else { swal('Error', 'Invalid file type', 'error') return !this.isValid } },
มาเขียนสคริปต์ง่ายๆ ที่จะสลับรูปแบบกัน นั่นคือ ควรแสดงเฉพาะเมื่อเราต้องการเพิ่มเพลงใหม่
เราสามารถทำได้โดยแก้ไขปุ่ม 'เพิ่มเพลง' ในตารางที่แสดงเพลงทั้งหมดที่สามารถพบได้:
<button class="btn btn-info m-3" @click="initForm"> {{addState?"Cancel":"Add New Music"}} </button>
จากนั้น เพิ่มสถานะที่จะเก็บสถานะของแบบฟอร์มในคุณสมบัติ data
:
addState: false
หลังจากทำสิ่งนี้ มากำหนดฟังก์ชัน initForm
กัน:
initForm() { this.addState = !this.addState },
จากนั้นเพิ่ม v-if="addState"
ให้กับ div
ที่มีแบบฟอร์ม:
<div class="card" v-if="addState">
การลบเพลง
ในการลบเพลง เราต้องเรียกจุดสิ้นสุดการ delete
และส่ง music id
เป็นพารามิเตอร์ มาเพิ่มเหตุการณ์การ click
ให้กับปุ่ม 'ลบ' ที่จะทริกเกอร์ฟังก์ชันให้ลบฟังก์ชัน:
<button class="btn btn-info" @click="deleteMusic(music._id)">Delete</button>
ฟังก์ชันการ delete
จะทำการร้องขอ HTTP ไปยังบริการแบ็คเอนด์ของเรา หลังจากได้รับ ID เพลงจากพารามิเตอร์ฟังก์ชัน deleteMusic
เราจะเพิ่ม ID ใน URL ที่เราใช้ส่งคำขอ ระบุชิ้นส่วนของเพลงที่ควรลบออกจากฐานข้อมูล
deleteMusic(id) { swal({ title: 'Are you sure?', text: 'Once deleted, you will not be able to recover this Music!', icon: 'warning', buttons: true, dangerMode: true }).then(willDelete => { if (willDelete) { this.$axios .$delete('/music/' + id) .then(response => { this.getAllMusics() swal('Poof! Your Music file has been deleted!', { icon: 'success' }) }) .catch(err => { swal('Error', 'Somethimg went wrong', 'error') }) } else { swal('Your Music file is safe!') } }) }
ทั้งหมดนี้ เราเพิ่งสร้างโปรแกรมจัดการเพลงของเรา ตอนนี้ได้เวลาสร้างเครื่องเล่นเพลงแล้ว
เริ่มต้นด้วยการสร้างโฟลเดอร์ใหม่ในโฟลเดอร์ส่วนประกอบชื่อ /player
จากนั้นสร้างไฟล์ player.vue ภายในโฟลเดอร์นี้และเพิ่มสิ่งนี้:
<template> <section> <div class="container"> <div class="row"> <div class="col-md-12"> <h3 class="text-center">Player</h3> </div> </div> </div> </section> </template> <script> export default { data() { return {} } } </script> <style scoped> </style>
ต่อไป มานำเข้าส่วนประกอบนี้ในไฟล์ index.vue ในโฟลเดอร์ /pages
แทนที่รหัสในไฟล์ index.vue เป็นสิ่งนี้:
<template> <div> <player /> </div> </template> <script> import player from '@/components/player/player' export default { components: { player } } </script>
มากำหนดค่าการกำหนดเส้นทางในองค์ประกอบ navbar
เพื่อเปิดใช้งานการกำหนดเส้นทางระหว่างเพจของเรา
ในการกำหนดเส้นทางในแอปพลิเคชัน nuxt-link
จะใช้หลังจากที่คุณได้ระบุหน้าสำหรับเส้นทางนั้นไปยังอินสแตนซ์เฉพาะ มาแก้ไขโค้ดในองค์ประกอบ partials/navbar
เป็นดังนี้:
<template> <header> <nav class="navbar navbar-expand-lg navbar-light bg-info"> <div class="container"> <nuxt-link to="/" class="navbar-brand">Music App</nuxt-link> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation" > <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse justify-content-end"> <ul class="navbar-nav"> <li class="nav-item active"> <nuxt-link to="/" class="nav-link">Player</nuxt-link> </li> <li class="nav-item"> <nuxt-link to="/manager" class="nav-link">Manager</nuxt-link> </li> </ul> </div> </div> </nav> </header> </template> <style scoped> .nav-link, .navbar-brand { color: #ffff !important; } </style>
ด้วยวิธีนี้ เราสามารถนำทางผ่านหน้าต่างๆ ของเราได้โดยใช้แถบนำทาง
การสร้างผู้เล่น
ก่อนที่เราจะเริ่ม เราต้องขยาย Webpack เพื่อโหลดไฟล์เสียง ไฟล์เสียงควรได้รับการประมวลผลโดย file-loader
ตัวโหลดนี้รวมอยู่ในการกำหนดค่าเริ่มต้นของ Webpack แล้ว แต่ไม่ได้ตั้งค่าให้จัดการไฟล์เสียง
ในการดำเนินการนี้ ให้ไปที่ไฟล์ nuxt.config.js และแก้ไข build
วด์อ็อบเจ็กต์เป็น:
build: { extend(config, ctx) { config.module.rules.push({ test: /\.(ogg|mp3|mp4|wav|mpe?g)$/i, loader: 'file-loader', options: { name: '\[path\][name].[ext]' } }) } }
ต่อไป มาเขียนฟังก์ชันที่จะรับเพลงทั้งหมด แล้วใช้ตัวสร้าง Audio
เพื่อเล่นเพลงแรกในอาร์เรย์ allMusic
สำหรับการเริ่มต้น มาแก้ไขไฟล์ player.vue ของเราเป็น:
<template> <section v-if="allMusic"> <div class="container"> <div class="row"> <div class="col-md-12"> <h3 class="text-center">Player</h3> </div> </div> <div class="row"> <div class="col-md-6"> <span>{{this.current.title}} - {{this.current.artist}}</span> </div> </div> </div> </section> </template> <script> export default { data() { return { current: { title: '', artist: '' }, song: true, isplaying: false, allMusic: null, index: 0, player: '' } }, methods: { async initPlayer() { if (this.allMusic !== []) { this.current = await this.allMusic[this.index] this.player.src = `https://localhost:4000/${this.current.music.path}` } else { this.song = true } }, async getAllSongs() { try { let response = await this.$axios.$get('/music') console.log(response) if (response === []) { this.song = true this.current = null } else { this.song = false this.allMusic = response } await this.initPlayer() } catch (err) { this.current = null console.log(err) } } }, created() { if (process.client) { this.player = new Audio() } this.getAllSongs() } } </script> <style scoped> </style>
เมื่อส่งไฟล์แล้ว เพลงจะเล่นเป็นแบ็กกราวด์ จากนั้นคุณจะสามารถเห็นสิ่งนี้ในเบราว์เซอร์ของคุณ:
หากต้องการหยุดเพลง สิ่งที่คุณต้องทำคือใส่ความคิดเห็นที่ await player.play()
ในฟังก์ชัน initPlayer
การสร้าง UI ของผู้เล่น
ตอนนี้มากำหนด UI เครื่องเล่นเพลงของเราโดยแทนที่เทมเพลตในไฟล์ player.vue ด้วยสิ่งต่อไปนี้:
<template> <section v-if="allMusic"> <div class="container"> <div class="row mb-5"> <div class="col-md-12"> <h3 class="text-center">Player</h3> </div> </div> <div class="row mt-5"> <div class="col-md-6"> <img src="https://images.pexels.com/photos/3624281/pexels-photo-3624281.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" class="image" /> <div class="card player_card"> <div class="card-body"> <h6 class="card-title"> <b>{{this.current.title}} - {{this.current.artist}}</b> </h6> <div> <i class="fas fa-backward control mr-4"></i> <i class="fas fa-play play"></i> <i class="fas fa-pause play"></i> <i class="fas fa-forward control ml-4"></i> </div> </div> </div> </div> <div class="col-md-6"> <div class="card shadow"> <table class="table"> <thead> <tr> <th scope="col">#</th> <th scope="col">Title</th> <th scope="col">Artist</th> <th scope="col">Action</th> </tr> </thead> <tbody> <tr> <th scope="row">1</th> <td>Mark</td> <td>Otto</td> <td> <button class="btn btn-primary">Play</button> </td> </tr> </tbody> </table> </div> </div> </div> </div> </section> </template>
จากนั้น เพิ่มสไตล์ต่อไปนี้ลงในส่วน style
:
<style scoped> .image { border-radius: 5px !important; position: relative; height: 300px; width: 100%; } .player_card { text-align: center; bottom: 20px; margin: 0px 40px; } .text-muted { font-size: 15px; } .play { font-size: 40px; } .control { font-size: 25px; } </style>
หลังจากแก้ไขแล้ว ผู้เล่นควรมีลักษณะดังนี้:
การเพิ่มฟังก์ชั่นการเล่น
เราจะดำเนินการต่อโดยแสดงคำอธิบายเพลงบนโต๊ะ ในการดำเนินการนี้ ให้แทนที่ตารางด้วยรหัสด้านล่าง:
<table class="table"> <thead> <tr> <th scope="col">#</th> <th scope="col">Title</th> <th scope="col">Artist</th> <th scope="col">Action</th> </tr> </thead> <tbody> <tr v-for="(music,index) in allMusic" :key="index"> <th scope="row">{{index+1}}</th> <td>{{music.title}}</td> <td>{{music.artist}}</td> <td> <button class="btn btn-primary">Play</button> </td> </tr> </tbody> </table>
เราไม่ต้องการแสดงไอคอน "เล่น" และ "หยุดชั่วคราว" พร้อมกัน แต่เราต้องการสถานการณ์ที่เมื่อเล่นเพลง ไอคอน "หยุดชั่วคราว" จะปรากฏขึ้น นอกจากนี้ เมื่อเพลงหยุดชั่วคราว ไอคอนการเล่นควรแสดงขึ้น
เพื่อให้บรรลุสิ่งนี้ เราจำเป็นต้องตั้งค่าสถานะ isPlaying
เป็นอินสแตนซ์ false
จากนั้นใช้อินสแตนซ์นี้เพื่อสลับไอคอน หลังจากนั้น เราจะเพิ่มฟังก์ชันให้กับไอคอน "เล่น"
isplaying:false
หลังจากทำเช่นนี้ ให้แก้ไขไอคอน 'เล่น' และ 'หยุดชั่วคราว' เป็น:
<i class="fas fa-play play" v-if="!isplaying" @click="play"></i> <i class="fas fa-pause play" v-else></i>
ทั้งหมดนี้ มากำหนดวิธีการ play
กัน:
play(song) { console.log(song) if (song) { this.current = song this.player.src = `https://localhost:4000/${this.current.music.path}` } this.player.play() this.isplaying = true },
อันดับแรก เรารับเพลงปัจจุบันและส่งไปยังพารามิเตอร์ของ function
จากนั้นเราจะกำหนดอินสแตนซ์ JavaScript Audio()
ต่อไป เราตรวจสอบว่าเพลงนั้นเป็นโมฆะหรือไม่ หากไม่ใช่ เราตั้งค่า this.current
เป็นเพลงที่เราส่งผ่านในพารามิเตอร์ จากนั้นเราเรียกอินสแตนซ์เครื่องเล่น Audio
(และอย่าลืมว่าเราต้องตั้งค่าสถานะ isPlaying
true
เมื่อเล่นเพลง)
การเพิ่มฟังก์ชันหยุดชั่วคราว
ในการหยุดเพลงชั่วคราว เราจะใช้วิธีหยุด Audio
ชั่วคราว เราจำเป็นต้องเพิ่มเหตุการณ์การ click
ไปที่ไอคอนหยุดชั่วคราว:
<i class="fas fa-pause play" @click="pause" v-else></i>
แล้วกำหนดฟังก์ชันในตัวอย่าง methods
:
pause() { this.player.pause() this.isplaying = false },
เล่นเพลงจากรายการเพลง
การดำเนินการนี้ค่อนข้างง่าย สิ่งที่เราต้องทำคือเพิ่มเหตุการณ์การ click
ที่จะเปลี่ยนพารามิเตอร์ song
ในวิธีการ play
เป็นเพลงที่เราเพิ่งสร้างขึ้น
เพียงแก้ไขปุ่ม play
บนตารางรายการเพลงเป็นดังนี้:
<button class="btn btn-primary" @click="play(music)">Play</button>
และคุณมีมัน!
การเพิ่มฟังก์ชันถัดไป
ในการเพิ่มฟังก์ชันถัดไป เราต้องเพิ่มดัชนีทีละรายการ ในการดำเนินการนี้ ให้เพิ่มเหตุการณ์การ click
ไปที่ไอคอนถัดไป:
@click="next"
จากนั้นกำหนดฟังก์ชัน prev
ในอินสแตนซ์ methods
:
next() { this.index++ if (this.index > this.allMusic.length - 1) { this.index = 0 } this.current = this.allMusic[this.index] this.play(this.current) },
เงื่อนไขนี้มีหน้าที่ในการเล่นซ้ำเพลงทั้งหมดทุกครั้งที่เล่นเพลงสุดท้ายในรายการ
การเพิ่มฟังก์ชัน previous
นี่เป็นสิ่งที่ตรงกันข้ามกับฟังก์ชันถัดไป เรามาเพิ่มเหตุการณ์การ click
ให้กับฟังก์ชันก่อนหน้ากัน:
@click="prev"
ต่อไป เรากำหนดฟังก์ชันก่อนหน้า:
prev() { this.index-- if (this.index < 0) { this.index = this.allMusic.length - 1 } this.current = this.allMusic[this.index] this.play(this.current) },
แอพเครื่องเล่นเพลงของเราเสร็จสมบูรณ์แล้ว!
บทสรุป
ในบทความนี้ เรามาดูกันว่าเราจะสร้างโปรแกรมจัดการเพลงด้วย Nuxt.js และ Express.js ได้อย่างไร ระหว่างทาง เราได้เห็นวิธีที่ Multer ปรับปรุงกระบวนการจัดการการอัปโหลดไฟล์และวิธีใช้ Mongoose เพื่อโต้ตอบโดยไม่ต้องใช้ฐานข้อมูล สุดท้าย เราใช้ Nuxt.js เพื่อสร้างแอปไคลเอ็นต์ซึ่งให้ความรู้สึกที่รวดเร็วและฉับไว
ต่างจากเฟรมเวิร์กอื่นๆ การสร้างแอปพลิเคชันด้วย Nuxt.js และ Express.js นั้นค่อนข้างง่ายและรวดเร็ว ส่วนที่ยอดเยี่ยมเกี่ยวกับ Nuxt.js คือวิธีที่มันจัดการเส้นทางของคุณและทำให้คุณจัดโครงสร้างแอปของคุณได้ดีขึ้น
- คุณสามารถเข้าถึงข้อมูลเพิ่มเติมเกี่ยวกับ Nuxt.js ได้ที่นี่
- คุณสามารถเข้าถึงซอร์สโค้ดบน Github ได้ที่นี่