كيفية إنشاء مدير موسيقى باستخدام Nuxt.js و Express.js

نشرت: 2022-03-10
ملخص سريع ↬ يقدم هذا المقال كيفية تبسيط Multer لعملية معالجة تحميلات الملفات. يقدم أيضًا كيفية استخدام Mongoose للتفاعل مع قاعدة البيانات الخاصة بنا من خلال إنشاء تطبيق مدير الموسيقى باستخدام Express.js جنبًا إلى جنب مع Multer لتحميل الموسيقى و Nuxt.js (إطار عمل Vue) للواجهة الأمامية الخاصة بنا.

قد يكون التعامل مع أصول الوسائط الرقمية مثل الصوت والفيديو في تطبيقك أمرًا صعبًا بسبب الاعتبارات التي يجب إجراؤها من جانب الخادم (مثل الشبكات والتخزين والطبيعة غير المتزامنة للتعامل مع تحميلات الملفات). ومع ذلك ، يمكننا استخدام مكتبات مثل 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 .

ثم نحفظ المثيل السريع في متغير يسمى app . يمكننا استخدام نسخة app لتكوين البرامج الوسيطة في تطبيقنا تمامًا كما قمنا بتكوين البرامج الوسيطة cors . نستخدم أيضًا مثيل app لإعداد مسار الجذر الذي سيتم تشغيله في المنفذ الذي حددناه.

لنقم الآن بإنشاء مجلد /config config قاعدة البيانات الخاصة بنا وتكوين multer :

 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 باستخدام Terminal
معاينة المحطة الطرفية (معاينة كبيرة)

إعداد النموذج والطرق وأجهزة التحكم

لنقم بإعداد بنية ملف عن طريق كتابة ما يلي:

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

بعد ذلك ، نكتب مدققًا بسيطًا يتحقق من نوع الملف قبل التحميل . ثم نقوم بتعريف مثيل multer عن طريق إضافة موقع التخزين ، وحدود كل ملف ، والمدقق الذي أنشأناه.

قم بإنشاء الطرق الضرورية

لنقم الآن بإنشاء طرقنا. فيما يلي قائمة بالنقاط النهائية التي سننشئها.

HTTP POST /music أضف موسيقى جديدة
HTTP GET /music احصل على كل الموسيقى
HTTP DELETE /music/:blogId احذف الموسيقى

لنبدأ بإنشاء مسار المدونة. توجه إلى api /ways / 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 الموجودة في ملف "وحدات التحكم".

دعنا ننتقل إلى api/controllers/musicController لتحديد وحدات التحكم. نبدأ بكتابة دالة للحصول على كل الموسيقى في قاعدة البيانات الخاصة بنا باستخدام طريقة mongoose db.collection.find التي ستعيد جميع العناصر الموجودة في تلك المجموعة.

بعد القيام بذلك ، نكتب وظيفة أخرى من شأنها إنشاء مقطوعة موسيقية جديدة في قاعدة البيانات. نحتاج إلى إنشاء مثيل موسيقى جديد باستخدام الكلمة الأساسية new ثم تحديد كائن الموسيقى. بعد القيام بذلك ، سنستخدم طريقة save النمس لإضافة موسيقى جديدة إلى قاعدة البيانات.

لحذف قطعة موسيقية ، نحتاج إلى استخدام طريقة remove النمس عن طريق تمرير معرف الموسيقى كمعامل في مثيل remove . ينتج عن هذا النمس البحث في مجموعة الموسيقى التي تحتوي على هذا المعرف المعين ثم إزالتها من تلك المجموعة.

 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 لنقطة النهاية ، ثم انقر فوق علامة تبويب النص الأساسي لتحديد الطريقة التي تريد بها إرسال بياناتك. (في حالتنا ، سنستخدم طريقة بيانات النموذج.)

لذا انقر فوق بيانات النموذج وقم بإعداد مفتاح النموذج الخاص بك. أثناء إعداده ، امنح المفاتيح بعض القيمة كما هو موضح في الصورة أدناه:

اختبار إضافة واجهة برمجة تطبيقات جديدة للموسيقى باستخدام Postman
اختبار إضافة واجهة برمجة تطبيقات جديدة للموسيقى في لوحة معلومات Postman (معاينة كبيرة)

بعد القيام بذلك ، انقر فوق "إرسال" لتقديم الطلب.

سرد جميع الموسيقى

لسرد جميع الموسيقى في قاعدة البيانات الخاصة بنا ، يتعين علينا كتابة عنوان URL لنقطة النهاية في قسم URL المتاح. بعد القيام بذلك ، انقر فوق الزر "إرسال" لتقديم الطلب.

اختبار قائمة API باستخدام ساعي البريد
اختبار قائمة API في لوحة معلومات Postman (معاينة كبيرة)

حذف الموسيقى

لحذف قطعة موسيقية ، نحتاج إلى تمرير music id .

اختبار حذف API باستخدام ساعي البريد
اختبار حذف لوحة معلومات API Postman (معاينة كبيرة)

هذا هو!

بناء الواجهة

بالنسبة إلى الواجهة الأمامية ، سنستخدم إطار عمل 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 musicapp
project description تطبيق مدير موسيقى بسيط
Author name <اسمك>
Package manager npm
UI framework Bootstrap vue
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

سنستخدم المحاور لتقديم طلب HTTP axios الخلفي. تم تثبيت Axios بالفعل في مشروعنا ، لذلك علينا فقط تكوين عنوان URL الأساسي - baseURL الخلفي.

للقيام بذلك ، افتح ملف nuxt.config.js في الدليل root وأضف baseURL في كائن axios .

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

بناء مدير الموسيقى

إعداد واجهة المستخدم

لنبدأ بتنظيف واجهة المستخدم. افتح ملف pages / index.vue وقم بإزالة جميع التعليمات البرمجية الموجودة هناك بما يلي:

 <template> <div>Hello</div> </template>

بعد القيام بذلك ، يجب أن تكون قادرًا فقط على رؤية كلمة "مرحبًا" في المتصفح.

في الدليل root ، قم بإنشاء مجلد /partials . داخل مجلد /partials parts ، أنشئ ملف 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 Navbar (معاينة كبيرة)

لنقم الآن بإعداد واجهة المستخدم لمديرنا. للقيام بذلك ، نحتاج إلى إنشاء مجلد /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 - يجب أن ترى هذا:

واجهة مستخدم مدير الموسيقى
واجهة مستخدم مدير الموسيقى (معاينة كبيرة)

سرد جميع الموسيقى

دعنا نواصل من خلال إنشاء وظيفة تجلب كل الموسيقى. سيتم تسجيل هذه الوظيفة في خطاف دورة الحياة الذي تم إنشاؤه ، بحيث يتم استدعاء الوظيفة كلما تم إنشاء المكون.

لنبدأ بإنشاء متغير في مثيل 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 داخل المكون الإضافي instace مثل هذا:

 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 ، سنضيف المعرف في عنوان 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.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>

بمجرد تقديم الملف ، سيتم تشغيل الموسيقى في الخلفية وبعد ذلك يجب أن تكون قادرًا على رؤية ذلك في متصفحك:

واجهة مستخدم مشغل الموسيقى
واجهة مستخدم مشغل الموسيقى (معاينة كبيرة)

لإيقاف الموسيقى ، كل ما عليك فعله هو التعليق على await player.play() في وظيفة initPlayer .

إنشاء واجهة مستخدم المشغل

دعنا الآن نحدد واجهة مستخدم مشغل الموسيقى الخاصة بنا عن طريق استبدال القالب الموجود في ملف 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 هنا.
  • يمكنك الوصول إلى الكود المصدري على جيثب هنا