Come creare un gestore musicale con Nuxt.js ed Express.js
Pubblicato: 2022-03-10La gestione di risorse multimediali digitali come audio e video nell'applicazione può essere complicata a causa delle considerazioni che devono essere fatte lato server (ad es. rete, archiviazione e natura asincrona della gestione dei caricamenti di file). Tuttavia, possiamo utilizzare librerie come Multer ed Express.js per semplificare il nostro flusso di lavoro sul back-end mentre utilizziamo Nuxt.js (framework Vue) per creare interazioni front-end.
Ogni volta che un client Web carica un file su un server, viene generalmente inviato tramite un modulo e codificato come multipart/form-data
. Multer
è un middleware per Express.js e Node.js che semplifica la gestione di questi cosiddetti multipart/form-data
ogni volta che gli utenti caricano file. In questo tutorial spiegherò come creare un'app di gestione della musica utilizzando Express.js con Multer per caricare musica e Nuxt.js (Vue framework) per il nostro frontend.
Prerequisiti
- Familiarità con HTML, CSS e JavaScript (ES6+);
- Node.js, npm e MongoDB installati sulla tua macchina di sviluppo;
- Codice VS o qualsiasi editor di codice a tua scelta;
- Conoscenza di base di Express.js.
Costruire il servizio di back-end
Iniziamo creando una directory per il nostro progetto navigando nella directory ed emettendo npm init -y
sul tuo terminale per creare un file package.json che gestisca tutte le dipendenze per la nostra applicazione.
mkdir serverside && cd serverside npm init -y
Quindi, installa multer
, express
e le altre dipendenze necessarie per avviare un'app Express.js.
npm install express multer nodemon mongoose cors morgan body-parser --save
Quindi, crea un file index.js :
touch index.js
Quindi, nel file index.js , inizializzeremo tutti i moduli, creeremo un'app Express.js e creeremo un server per la connessione ai browser:
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}`); });
Prima di tutto, inseriamo Express.js nel progetto e quindi definiamo una porta su cui verrà eseguita la nostra applicazione. Successivamente, introduciamo le dipendenze body-parser
, morgan
, mongoose
e cors
.
Quindi salviamo l'istanza express in una variabile chiamata app
. Possiamo utilizzare l'istanza app
per configurare il middleware nella nostra applicazione proprio come abbiamo configurato il middleware cors
. Usiamo anche l'istanza app
per impostare il percorso principale che verrà eseguito nella porta che abbiamo definito.
Creiamo ora una cartella /config
per il nostro database config
e multer
config:
mkdir config and cd config touch multer.js && touch db.js
Quindi apri config/db.js e aggiungi il seguente codice per configurare il nostro database:
module.exports = { database: "mongodb://localhost:27017/", secret: "password" };
(Questo è in realtà un oggetto che contiene l'URL del database e il segreto del database.)
L'esecuzione di nodemon
e la navigazione su localhost:4000
sul tuo browser dovrebbero darti questo messaggio:
"Hola MEVN devs...Assemble"
Inoltre, questo è l'aspetto che dovrebbe avere il tuo terminale:
Configurazione di modello, percorsi e controller
Impostiamo una struttura di file digitando quanto segue:
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
Nel nostro terminale, utilizziamo mkdir
per creare una nuova directory, quindi cd
per spostarci in una directory. Quindi iniziamo creando una directory chiamata api
e poi ci spostiamo nella directory api
.
Il comando touch
viene utilizzato per creare un nuovo file all'interno di una directory utilizzando il terminale, mentre il comando cd
viene utilizzato per uscire da una directory.
Ora andiamo al nostro file api/model/Music.js per creare uno schema musicale. Un modello è una classe con la quale costruiamo documenti. In questo caso, ogni documento sarà un brano musicale con proprietà e comportamenti dichiarati nel nostro schema:
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;
Andiamo su config/multer
per configurare 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 });
Nel file multer.js , iniziamo impostando una cartella in cui verranno caricati tutti i file musicali caricati. Dobbiamo rendere questo file statico definendolo nel file index.js :
app.use('/uploads', express.static('uploads'));
Successivamente, scriviamo un semplice validatore che verificherà il tipo mime del file prima del caricamento. Definiamo quindi l'istanza di multer
aggiungendo la posizione di archiviazione, i limiti di ciascun file e il validatore che abbiamo creato.
Crea i percorsi necessari
Ora creiamo i nostri percorsi. Di seguito è riportato l'elenco degli endpoint che creeremo.
HTTP POST /music | Aggiungi nuova musica |
HTTP GET /music | Ottieni tutta la musica |
HTTP DELETE /music/:blogId | Elimina una musica |
Iniziamo creando il percorso del blog. Vai su api/routes/music.js e scrivi il seguente codice:
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;
Nota : ora ogni volta che facciamo una richiesta get
a /music
. il percorso chiama la funzione getAllMusic
che si trova nel file 'controllers'.
Passiamo ad api/controllers/musicController
per definire i controller. Iniziamo scrivendo una funzione per ottenere tutta la musica nel nostro database utilizzando il metodo mongoose db.collection.find
che restituirà tutti gli elementi in quella raccolta.
Dopo averlo fatto, scriviamo un'altra funzione che creerà un nuovo brano musicale nel database. Dobbiamo creare una nuova istanza musicale utilizzando la new
parola chiave e quindi definire l'oggetto musicale. Dopo aver fatto ciò, utilizzeremo il metodo di save
della mangusta per aggiungere nuova musica al database.
Per eliminare un brano musicale, è necessario utilizzare il metodo di remove
mangusta semplicemente passando l'ID musica come parametro nell'istanza di remove
. Ciò si traduce in mangusta che esamina la raccolta musicale che ha quel particolare ID e quindi la rimuove da quella raccolta.
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); } };
Ultimo ma non meno importante, per testare i percorsi, dobbiamo registrare i percorsi musicali nel nostro file index.js :
const userRoutes = require("./api/user/route/user"); //bring in our user routes app.use("/user", userRoutes);
Testare i punti finali
Per testare i nostri endpoint, utilizzeremo POSTMAN.
Aggiunta di nuova musica
Per testare la funzionalità Add Music
, imposta il metodo della richiesta cliccando sul menu a tendina dei metodi. Dopo aver fatto ciò, digita l'URL dell'endpoint e quindi fai clic sulla scheda del corpo per selezionare come desideri inviare i tuoi dati. (Nel nostro caso, utilizzeremo il metodo form-data.)
Quindi fai clic sui dati del modulo e imposta la chiave del tuo modello. Durante la configurazione, dai alle chiavi un valore come mostrato nell'immagine qui sotto:
Dopo aver fatto ciò, fare clic su "Invia" per effettuare la richiesta.
Elenco di tutta la musica
Per elencare tutta la musica nel nostro database, dobbiamo digitare l'URL dell'endpoint nella sezione URL fornita. Dopo aver fatto ciò, fare clic sul pulsante "Invia" per effettuare la richiesta.
Eliminazione di musica
Per eliminare un brano musicale, dobbiamo passare l' music id
come parametro.
Questo è tutto!
Costruire il frontend
Per il nostro frontend, utilizzeremo un framework Vue: Nuxt.js.
“Nuxt è un framework progressivo basato su Vue.js per creare moderne applicazioni web. Si basa sulle librerie ufficiali di Vue.js (vue, vue-router e vuex) e potenti strumenti di sviluppo (webpack, Babel e PostCSS).”
— Guida NuxtJS
Per creare una nuova applicazione Nuxt.js, apri il tuo terminale e digita quanto segue (con musicapp
come nome dell'app che creeremo):
$ npx create-nuxt-app musicapp
Durante il processo di installazione, ci verranno poste alcune domande relative alla configurazione del progetto:
Project name | musicaapp |
project description | Una semplice app per la gestione della musica |
Author name | <il tuo nome> |
Package manager | npm |
UI framework | Bootstrap vue |
custom ui framework | nessuno |
Nuxt modules | Axios,pwa (usa la barra spaziatrice sulla tastiera per selezionare gli elementi) |
Linting tool | Più carino |
test framework | Nessuno |
Rendering Mode | Universale (SSR) |
development tool | Jsonconfig.json |
Dopo aver selezionato tutto questo, dobbiamo aspettare un po' prima che il progetto venga impostato. Una volta pronto, spostati nella cartella /project
e servi il progetto come segue:
cd musicapp && npm run dev
Apri il progetto in qualsiasi editor di codice di tua scelta e quindi apri il progetto nel browser accedendo a localhost:3000
.
Configurazione di Axios
axios
per effettuare una richiesta HTTP al nostro server back-end. Axios è già installato nel nostro progetto, quindi dobbiamo solo configurare l' baseURL
di base - sul nostro server di back-end.
Per fare ciò, apri il file nuxt.config.js nella root
e aggiungi l'URL axios
baseURL
axios: { baseURL:'https://localhost:4000' },
Costruire il Music Manager
Configurazione dell'interfaccia utente
Iniziamo ripulendo l'interfaccia utente. Apri il file pages/index.vue e rimuovi tutto il codice con quanto segue:
<template> <div>Hello</div> </template>
Dopo aver fatto ciò, dovresti essere in grado di vedere solo un "Ciao" nel browser.
Nella root
, crea una cartella /partials
. All'interno della cartella /partials
partials, crea un file navbar.vue e aggiungi il seguente codice:
<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>
Nota : utilizzeremo il componente per navigare tra le pagine della nostra applicazione. Questo sarà solo un semplice componente costituito dalla barra di navigazione Bootstrap navbar
Consulta la documentazione ufficiale di Bootstrap per ulteriori riferimenti.
Quindi, definiamo un layout personalizzato per l'applicazione. Apri la cartella /layouts
, sostituisci il codice nel file default.vue con il codice seguente.
<template> <div> <navbar /> <nuxt /> </div> </template> <script> import navbar from '@/partial/navbar' export default { components: { navbar } } </script>
Importiamo la navbar
di navigazione in questo layout, il che significa che tutte le pagine della nostra applicazione navbar
quel componente della barra di navigazione. (Questo sarà il componente su cui verranno montati tutti gli altri componenti nella nostra applicazione.)
Dopo questo, dovresti essere in grado di vedere questo nel tuo browser:
Ora impostiamo l'interfaccia utente per il nostro manager. Per fare ciò, dobbiamo creare una cartella /manager
all'interno della cartella dei componenti e quindi aggiungere un file nella cartella denominata manager.vue .
In questo file, aggiungi il seguente codice:
<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>
Nota : questo è solo un semplice modello Bootstrap per aggiungere musica nella nostra applicazione. Il modulo definirà un modello di tabella che elencherà tutta la musica che può essere trovata nel nostro database.
Dopo aver definito questo componente, è necessario registrarlo nella cartella /pages
per inizializzare il routing.
Nuxt.js non ha un file "router.js" come Vue.js. Utilizza la cartella delle pagine per l'instradamento. Per maggiori dettagli, visitare il sito Web Nuxt.js.
Per registrare il componente, creare una cartella /manager
all'interno della cartella /pages
e creare un file index.vue . Quindi, inserisci il seguente codice all'interno del file:
<template> <div> <manager /> </div> </template> <script> import manager from '@/components/manager/manager' export default { components: { manager } } </script>
Questo è il componente che renderà il percorso delle nostre pages
.
Dopo aver fatto ciò, vai al tuo browser e vai a /manager
: dovresti vedere questo:
Elenco di tutta la musica
Continuiamo creando una funzione che recupererà tutta la musica. Questa funzione verrà registrata nell'hook del ciclo di vita creato, in modo che ogni volta che viene creato il componente, la funzione verrà chiamata.
Iniziamo creando una variabile nell'istanza vue
che conterrà tutta la musica:
allmusic = []; musicLoading: false,
Quindi, definisci una funzione getAllMusics
e aggiungi il codice seguente:
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') } }
Quindi, registrati all'interno dell'hook del ciclo di vita creato:
created() { this.getAllMusics() }
Emissione dei dati
Ora è il momento di produrre tutte le canzoni sul tavolo che abbiamo creato in precedenza:
<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>
Ricordi quel tavolo che abbiamo creato prima? Bene, dovremo scorrere la risposta che riceviamo dal nostro back-end per elencare tutta la musica ricevuta dal database.
Aggiunta di musica
Per aggiungere un nuovo brano musicale dobbiamo fare una richiesta HTTP al server back-end con i dettagli della musica. Per fare ciò, iniziamo modificando il modulo e la gestione dei caricamenti dei file.
Nel modulo, è necessario aggiungere un listener di event
che ascolti il modulo quando viene inviato. Nel campo di input
, aggiungiamo un modello v-
per associare il valore al campo di input.
<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>
E la sezione dello script dovrebbe assomigliare a questa:
<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>
Definiremo una funzione che invierà una richiesta al nostro servizio di back-end per creare l'eventuale nuova musica che è stata aggiunta alla lista. Anche. abbiamo bisogno di scrivere una semplice funzione di convalida che verificherà il tipo di file in modo che gli utenti possano caricare solo file con un'estensione di .mp3 e .mp4 .
È importante definire una proprietà calcolata per assicurarsi che il nostro campo di input non sia vuoto. Abbiamo anche bisogno di aggiungere un semplice validatore che assicuri che il file che stiamo cercando di caricare sia effettivamente un file musicale.
Continuiamo modificando la funzione addMusic
per fare una richiesta al nostro servizio di back-end. Ma prima di farlo, installiamo prima sweetalert
che ci fornirà una bella finestra modale. Per fare ciò, apri il tuo terminale e digita quanto segue:
npm i sweetalert
Dopo aver installato il pacchetto, crea un file sweetalert.js nella cartella /plugins
e aggiungi questo:
import Vue from 'vue'; import swal from 'sweetalert'; Vue.prototype.$swal = swal;
Quindi, registra il plug-in nel file nuxt.config.js all'interno dell'istanza del plug-in in questo modo:
plugins: [ { src: '~/plugins/sweetalert' } ],
Ora abbiamo configurato con successo sweetalert
nella nostra applicazione, quindi possiamo andare avanti e modificare la funzione addmusic
su questo:
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 } },
Scriviamo un semplice script che alternerà il modulo, cioè dovrebbe essere visualizzato solo quando vogliamo aggiungere nuova musica.
Possiamo farlo modificando il pulsante "Aggiungi musica" nella tabella che mostra tutta la musica che puoi trovare:
<button class="btn btn-info m-3" @click="initForm"> {{addState?"Cancel":"Add New Music"}} </button>
Quindi, aggiungi uno stato che manterrà lo stato del modulo nella proprietà dei data
:
addState: false
Dopo aver fatto ciò, definiamo la funzione initForm
:
initForm() { this.addState = !this.addState },
E quindi aggiungi v-if="addState"
al div
che contiene il modulo:
<div class="card" v-if="addState">
Eliminazione di musica
Per eliminare la musica, dobbiamo chiamare l'endpoint di delete
e passare l' music id
come parametro. Aggiungiamo un evento click
al pulsante "Elimina" che attiverà la funzione per eliminare una funzione:
<button class="btn btn-info" @click="deleteMusic(music._id)">Delete</button>
La funzione di delete
effettuerà una richiesta HTTP al nostro servizio di back-end. Dopo aver ottenuto l'ID della musica dal parametro della funzione deleteMusic
, aggiungeremo l'ID nell'URL che stiamo utilizzando per inviare la richiesta. Questo specifica il brano musicale esatto che dovrebbe essere rimosso dal database.
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!') } }) }
Con tutto questo, abbiamo appena costruito il nostro manager musicale. Ora è il momento di costruire il lettore musicale.
Iniziamo creando una nuova cartella nella cartella dei componenti denominata /player
. Quindi, crea un file player.vue all'interno di questa cartella e aggiungi questo:
<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>
Quindi, importiamo questo componente nel file index.vue nella cartella /pages
. Sostituisci il codice nel file index.vue con questo:
<template> <div> <player /> </div> </template> <script> import player from '@/components/player/player' export default { components: { player } } </script>
Configuriamo il routing nel nostro componente navbar
per abilitare il routing tra le nostre pagine.
Per eseguire il routing in un'applicazione Nuxt.js, viene utilizzato il nuxt-link
dopo di che è stata specificata la pagina per tale route a un'istanza particolare. Quindi modifichiamo il codice nel componente partials/navbar
in questo modo:
<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>
Con questo, possiamo navigare attraverso le nostre pagine usando la barra di navigazione.
Costruire il giocatore
Prima di iniziare, è necessario estendere Webpack per caricare i file audio. I file audio devono essere elaborati da file-loader
. Questo caricatore è già incluso nella configurazione predefinita di Webpack, ma non è impostato per gestire i file audio.
Per fare ciò, vai al file nuxt.config.js e modifica l'oggetto build
in questo modo:
build: { extend(config, ctx) { config.module.rules.push({ test: /\.(ogg|mp3|mp4|wav|mpe?g)$/i, loader: 'file-loader', options: { name: '\[path\][name].[ext]' } }) } }
Quindi, scriviamo una funzione che otterrà tutti i brani e quindi utilizziamo il costruttore Audio
per riprodurre il primo brano nell'array allMusic
.
Per cominciare, modifichiamo il nostro file player.vue in questo:
<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>
Una volta che il file è stato servito, la musica verrà riprodotta in sottofondo e quindi dovresti essere in grado di vederlo nel tuo browser:
Per interrompere la musica, tutto ciò che devi fare è commentare await player.play()
nella funzione initPlayer
.
Creazione dell'interfaccia utente del giocatore
Definiamo ora l'interfaccia utente del nostro lettore musicale sostituendo il modello nel nostro file player.vue con il seguente:
<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>
Quindi, aggiungi il seguente stile nella sezione dello 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>
Dopo aver modificato questo, il giocatore dovrebbe apparire così:
Aggiunta della funzione di riproduzione
Continueremo visualizzando la descrizione della musica sul tavolo. Per fare ciò, sostituire la tabella con il codice seguente:
<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>
Non vogliamo visualizzare contemporaneamente le icone "Riproduci" e "Pausa". Invece, vogliamo una situazione in cui durante la riproduzione del brano, venga visualizzata l'icona "Pausa". Inoltre, quando il brano è in pausa, dovrebbe essere visualizzata l'icona di riproduzione.
Per ottenere ciò, è necessario impostare uno stato isPlaying
false
e quindi utilizzare questa istanza per attivare le icone. Successivamente, aggiungeremo una funzione alla nostra icona "Riproduci".
isplaying:false
Dopo aver fatto ciò, modifica l'icona "Riproduci" e "Pausa" in questo modo:
<i class="fas fa-play play" v-if="!isplaying" @click="play"></i> <i class="fas fa-pause play" v-else></i>
Con tutto questo definiamo il metodo di 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 },
Prima di tutto, prendiamo la canzone corrente e la passiamo nel parametro della function
. Definiamo quindi l'istanza JavaScript Audio()
. Successivamente, controlliamo se il brano è nullo: in caso contrario, impostiamo this.current
sul brano che abbiamo passato nel parametro, quindi chiamiamo l'istanza del lettore Audio
. (Inoltre, non dimenticare che dobbiamo impostare lo stato isPlaying
su true
quando la musica è in riproduzione.)
Aggiunta della funzione di pausa
Per mettere in pausa un brano, utilizzeremo il metodo di pausa Audio
. Dobbiamo aggiungere un evento click
all'icona di pausa:
<i class="fas fa-pause play" @click="pause" v-else></i>
E quindi definire la funzione nell'istanza dei methods
:
pause() { this.player.pause() this.isplaying = false },
Riproduzione di un brano dall'elenco musicale
Questo è abbastanza semplice da implementare. Tutto quello che dobbiamo fare è aggiungere un evento click
che cambierà il parametro del song
nel metodo di play
al brano che abbiamo appena creato.
Modifica semplicemente il pulsante di play
sulla tabella dell'elenco musicale in questo modo:
<button class="btn btn-primary" @click="play(music)">Play</button>
E il gioco è fatto!
Aggiunta della funzione successiva
Per aggiungere la funzione successiva, dobbiamo incrementare l'indice di uno. Per fare ciò, aggiungi un evento click
all'icona successiva:
@click="next"
E quindi definire la funzione prev
nell'istanza dei methods
:
next() { this.index++ if (this.index > this.allMusic.length - 1) { this.index = 0 } this.current = this.allMusic[this.index] this.play(this.current) },
Questo condizionale è responsabile della riproduzione di tutti i brani ogni volta che è stato riprodotto l'ultimo brano nell'elenco.
Aggiunta della funzione previous
Questo è in realtà l'opposto della funzione successiva, quindi aggiungiamo un evento click
alla funzione precedente:
@click="prev"
Successivamente, definiamo la funzione precedente:
prev() { this.index-- if (this.index < 0) { this.index = this.allMusic.length - 1 } this.current = this.allMusic[this.index] this.play(this.current) },
La nostra app per il lettore musicale è ora completa!
Conclusione
In questo articolo, abbiamo esaminato come creare un gestore musicale con Nuxt.js ed Express.js. Lungo la strada, abbiamo visto come Multer snellisce il processo di gestione dei caricamenti di file e come utilizzare Mongoose per interagire senza un database. Infine, abbiamo utilizzato Nuxt.js per creare l'app client che le conferisce una sensazione veloce e scattante.
A differenza di altri framework, la creazione di un'applicazione con Nuxt.js ed Express.js è abbastanza facile e veloce. La parte interessante di Nuxt.js è il modo in cui gestisce i tuoi percorsi e ti fa strutturare meglio le tue app.
- Puoi accedere a maggiori informazioni su Nuxt.js qui.
- Puoi accedere al codice sorgente su Github qui