Nuxt.js 및 Express.js로 뮤직 매니저를 구축하는 방법
게시 됨: 2022-03-10애플리케이션에서 오디오 및 비디오와 같은 디지털 미디어 자산을 처리하는 것은 서버 측에서 고려해야 하는 고려 사항(예: 네트워킹, 스토리지 및 파일 업로드 처리의 비동기 특성)으로 인해 까다로울 수 있습니다. 그러나 Multer 및 Express.js와 같은 라이브러리를 사용하여 백엔드에서 워크플로를 단순화하는 동시에 Nuxt.js(Vue 프레임워크)를 사용하여 프런트엔드 상호 작용을 구축할 수 있습니다.
웹 클라이언트가 서버에 파일을 업로드할 때마다 일반적으로 양식을 통해 제출되고 multipart/form-data
로 인코딩됩니다. Multer
는 Express.js 및 Node.js용 미들웨어로, 사용자가 파일을 업로드할 때마다 이러한 소위 multipart/form-data
를 쉽게 처리할 수 있습니다. 이 튜토리얼에서는 Multer와 함께 Express.js를 사용하여 음악을 업로드하고 프론트엔드용 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
및 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
종속성을 가져옵니다.
그런 다음 익스프레스 인스턴스를 app
이라는 변수에 저장합니다. cors
미들웨어를 구성한 것처럼 app
인스턴스를 사용하여 애플리케이션에서 미들웨어를 구성할 수 있습니다. 또한 app
인스턴스를 사용하여 정의한 포트에서 실행할 루트 경로를 설정합니다.
이제 데이터베이스 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;
Multer를 구성하기 위해 config/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'));
그런 다음 업로드하기 전에 파일 mimetype 을 확인하는 간단한 유효성 검사기를 작성합니다. 그런 다음 저장 위치, 각 파일의 제한 및 생성한 유효성 검사기를 추가하여 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;
참고 : 이제 /music
에 get
요청을 할 때마다 . 경로는 '컨트롤러' 파일에 있는 getAllMusic
함수를 호출합니다.
컨트롤러를 정의하기 위해 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 방식을 사용하겠습니다.)
따라서 양식 데이터를 클릭하고 모델 키를 설정하십시오. 설정할 때 아래 이미지와 같이 키에 값을 지정하십시오.
이 작업을 수행한 후 '보내기'를 클릭하여 요청하십시오.
모든 음악 나열
데이터베이스에 있는 모든 음악을 나열하려면 제공된 URL 섹션에 끝점 URL을 입력해야 합니다. 이 작업을 수행한 후 '보내기' 버튼을 클릭하여 요청을 보냅니다.
음악 삭제
음악을 삭제하려면 music id
를 매개변수로 전달해야 합니다.
그게 다야!
프론트엔드 구축
프론트엔드에서는 Vue 프레임워크인 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 | 뮤직앱 |
project description | 간단한 뮤직 매니저 앱 |
Author name | <당신의 이름> |
Package manager | npm |
UI framework | 부트스트랩 뷰 |
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 구성
우리는 백엔드 서버에 HTTP 요청을 하기 위해 axios
를 사용할 것입니다. Axios는 이미 프로젝트에 설치되어 있으므로 baseURL
을 백엔드 서버로 구성하기만 하면 됩니다.
이렇게 하려면 root
디렉터리에서 nuxt.config.js 파일을 열고 axios
개체에 baseURL
을 추가합니다.
axios: { baseURL:'https://localhost:4000' },
뮤직 매니저 구축
UI 설정
UI 정리부터 시작하겠습니다. pages/index.vue 파일을 열고 다음을 사용하여 거기에 있는 모든 코드를 제거합니다.
<template> <div>Hello</div> </template>
이렇게 하면 브라우저에서 "Hello"만 볼 수 있어야 합니다.
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
로 구성된 간단한 구성 요소가 될 것입니다 . 자세한 내용은 공식 부트스트랩 문서를 확인하세요.
다음으로 애플리케이션에 대한 사용자 정의 레이아웃을 정의하겠습니다. /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>
참고 : 이것은 애플리케이션에 음악을 추가하기 위한 단순한 부트스트랩 템플릿입니다. 이 양식은 데이터베이스에서 찾을 수 있는 모든 음악을 나열하는 테이블 템플릿을 정의합니다.
이 구성 요소를 정의한 후 라우팅을 시작하기 위해 /pages
폴더에 등록해야 합니다.
Nuxt.js에는 Vue.js와 같은 'router.js' 파일이 없습니다. 라우팅을 위해 페이지 폴더를 사용합니다. 자세한 내용은 Nuxt.js 웹사이트를 방문하세요.
구성 요소를 등록하려면 /pages
폴더 내에 /manager
폴더를 생성하고 index.vue 파일을 생성합니다. 그런 다음 파일 내부에 다음 코드를 배치합니다.
<template> <div> <manager /> </div> </template> <script> import manager from '@/components/manager/manager' export default { components: { manager } } </script>
이것은 pages
경로에서 렌더링할 구성 요소입니다.
이 작업을 수행한 후 브라우저로 이동하여 /manager
로 이동합니다. 다음과 같이 표시되어야 합니다.
모든 음악 나열
계속해서 모든 음악을 가져올 함수를 만들어 보겠습니다. 이 함수는 생성된 라이프 사이클 후크에 등록되어 컴포넌트가 생성될 때마다 함수가 호출됩니다.
모든 음악을 담을 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-
-model을 추가합니다.
<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
패키지를 설치한 후 /plugins
폴더에 sweetalert.js 파일을 만들고 다음을 추가합니다.
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 },
그런 다음 형식이 포함된 div
에 v-if="addState"
를 추가합니다.
<div class="card" v-if="addState">
음악 삭제
음악을 삭제하려면 delete
엔드포인트를 호출하고 music id
를 매개변수로 전달해야 합니다. 함수를 삭제하는 함수를 트리거하는 click
이벤트를 'Delete' 버튼에 추가해 보겠습니다.
<button class="btn btn-info" @click="deleteMusic(music._id)">Delete</button>
delete
기능은 백엔드 서비스에 HTTP 요청을 할 것입니다. deleteMusic
함수 매개변수에서 음악 ID를 가져온 후 요청을 보내는 데 사용하는 URL에 ID를 추가합니다. 이것은 데이터베이스에서 제거되어야 하는 정확한 음악을 지정합니다.
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>
다음으로 이 구성 요소를 /pages
폴더의 index.vue 파일로 가져오겠습니다. index.vue 파일의 코드를 다음으로 바꿉니다.
<template> <div> <player /> </div> </template> <script> import player from '@/components/player/player' export default { components: { player } } </script>
페이지 간 라우팅을 활성화하기 위해 navbar
구성 요소에서 라우팅을 구성해 보겠습니다.
Nuxt.js 애플리케이션에서 라우팅하기 위해 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>
파일이 제공되면 음악이 백그라운드에서 재생되고 브라우저에서 이를 볼 수 있습니다.
음악을 중지하려면 initPlayer
함수에서 await player.play()
를 주석 처리하기만 하면 됩니다.
플레이어 UI 만들기
이제 player.vue 파일의 템플릿을 다음으로 교체하여 음악 플레이어 UI를 정의해 보겠습니다.
<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()
인스턴스를 정의합니다. 다음으로 노래가 null인지 확인합니다. 그렇지 않은 경우 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 },
음악 목록에서 노래 재생
이것은 구현하기가 매우 간단합니다. 우리가 해야 할 일은 play
방법의 song
매개변수를 방금 만든 노래로 변경하는 click
이벤트를 추가하는 것입니다.
음악 목록 테이블의 play
버튼을 다음과 같이 수정하면 됩니다.
<button class="btn btn-primary" @click="play(music)">Play</button>
그리고 당신은 그것을 가지고 있습니다!
다음 기능 추가하기
다음 함수를 추가하려면 인덱스를 1씩 증가시켜야 합니다. 이렇게 하려면 다음 아이콘에 click
이벤트를 추가합니다.
@click="next"
그런 다음 methods
인스턴스에서 prev
함수를 정의합니다.
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의 소스 코드에 액세스할 수 있습니다.