如何使用 Nuxt.js 和 Express.js 构建音乐管理器

已发表: 2022-03-10
快速总结↬本文介绍 Multer 如何简化处理文件上传的过程。 它还介绍了如何使用 Mongoose 与我们的数据库进行交互,方法是使用 Express.js 和 Multer 构建音乐管理器应用程序用于音乐上传和 Nuxt.js(Vue 框架)用于我们的前端。

在您的应用程序中处理数字媒体资产(例如音频和视频)可能会很棘手,因为必须考虑到服务器端(例如网络、存储和处理文件上传的异步性质)。 但是,我们可以使用 Multer 和 Express.js 等库来简化后端的工作流程,同时使用 Nuxt.js(Vue 框架)来构建前端交互。

每当 Web 客户端将文件上传到服务器时,它通常通过表单提交并编码为multipart/form-dataMulter是 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

接下来,安装multerexpress和引导 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-parsermorganmongoosecors依赖项。

然后我们将 express 实例保存在一个名为app的变量中。 我们可以使用app实例在我们的应用程序中配置中间件,就像我们配置cors中间件一样。 我们还使用app实例来设置将在我们定义的端口中运行的根路由。

现在让我们为我们的数据库configmulter配置创建一个/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"

此外,您的终端现在应该是这样的:

使用终端运行 Nodemon
终端预览(大预览)

设置模型、路由和控制器

让我们通过键入以下内容来设置文件结构:

 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'));

之后,我们编写了一个简单的验证器,它将在上传之前检查文件的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关键字创建一个新的音乐实例,然后定义音乐对象。 完成此操作后,我们将使用 mongoose save方法将新音乐添加到数据库中。

为了删除一首音乐,我们需要使用 mongoose 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 方法。)

因此,单击表单数据并设置您的模型密钥。 当你设置它时,给键一些值,如下图所示:

测试使用 Postman 添加新的音乐 API
测试在 Postman 仪表板中添加新的音乐 API(大预览)

完成此操作后,单击“发送”以发出请求。

列出所有音乐

要列出我们数据库中的所有音乐,我们必须在提供的 URL 部分中键入端点 URL。 完成此操作后,单击“发送”按钮发出请求。

使用 Postman 测试列表 API
在 Postman 仪表板中测试列表 API(大预览)

删除音乐

要删除一段音乐,我们需要将music id作为参数传递。

使用 Postman 测试删除 API
测试删除 API Postman 仪表板(大预览)

而已!

构建前端

对于我们的前端,我们将使用 Vue 框架:Nuxt.js。

“Nuxt 是一个基于 Vue.js 的渐进式框架,用于创建现代 Web 应用程序。 它基于 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在浏览器中打开项目。

Nuxt.js 项目预览
Nuxt.js 项目预览(大预览)

配置 Axios

我们将使用axios向我们的后端服务器发出 HTTP 请求。 Axios 已经安装在我们的项目中,所以我们只需要配置baseURL - 到我们的后端服务器。

为此,请打开root目录中的nuxt.config.js文件,并将axios baseURL中。

 axios: { baseURL:'https://localhost:4000' },

构建音乐管理器

设置用户界面

让我们从清理 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组成的简单组件。 查看官方 Bootstrap 文档以获取更多参考。

接下来,让我们为应用程序定义一个自定义布局。 打开/layouts文件夹,将default.vue文件中的代码替换为以下代码。

 <template> <div> <navbar /> <nuxt /> </div> </template> <script> import navbar from '@/partial/navbar' export default { components: { navbar } } </script>

我们将navbar导入此布局,这意味着我们应用程序中的所有页面都将包含该navbar组件。 (这将是我们应用程序中所有其他组件将被挂载的组件。)

在此之后,您应该能够在浏览器中看到:

修改后的 Nuxt.js Navbar 组件
Nuxt.js 导航栏组件(大预览)

现在让我们为我们的经理设置 UI。 为此,我们需要在 components 文件夹中创建一个/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”文件。 它使用 pages 文件夹进行路由。 有关更多详细信息,请访问 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您应该会看到以下内容:

音乐管理器界面
音乐管理器 UI(大预览)

列出所有音乐

让我们继续创建一个可以获取所有音乐的函数。 该函数将注册在 created 生命周期钩子中,以便每当创建组件时,都会调用该函数。

让我们首先在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 },

然后将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 请求。 从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>

提供文件后,音乐将在后台播放,然后您应该能够在浏览器中看到:

音乐播放器界面
音乐播放器 UI(大预览)

要停止播放音乐,您只需在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>

修改后,播放器应如下所示:

音乐播放器最终 UI
音乐播放器的最终用户界面(大预览)

添加播放功能

我们将继续在桌子上显示音乐描述。 为此,请将表格替换为以下代码:

 <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事件,它将play方法中的song参数更改为我们刚刚创建的歌曲。

只需将音乐列表表上的play按钮修改为:

 <button class="btn btn-primary" @click="play(music)">Play</button>

你有它!

添加下一个函数

要添加下一个函数,我们需要将索引加一。 为此,请在下一个图标中添加一个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 上的源代码