ما هو المقال حول
الغرض من هذه المقالة هو إظهار كيف يمكنك إنشاء تطبيق MEVN أساسي. اختصار MEVN
يعني - MongoDB + Express.js + Vue.js + Node.js. كمثال ، سيتم كتابتها
تطبيق صفحة واحدة يحتوي على نموذج يتكون من عدة نص
الحقول. عند ملء النموذج وإرسال البيانات ، سيقوم الخادم بكتابتها في قاعدة البيانات ، و
إعادة توجيه العميل إلى صفحة "شكرًا لك".
يستخدم Ubuntu 18.10 كنظام تشغيل ، وسيتم تثبيت جميع المكونات
وأشار بالنسبة لها.
المتطلبات المطلوبة
- معرفة HTML ، CSS ؛
- المعرفة الأساسية جافا سكريبت.
ما لدينا في الخروج
- تطبيق Fullstack الكامل ؛
- عمليات CRUD وواجهات برمجة تطبيقات REST باستخدام Express.js ؛
- الاتصال MongoDB.
إعداد مساحة العمل
لبدء تطوير التطبيق ، تحتاج إلى تثبيت بعض الأدوات.
أساس المشروع بأكمله هو Node.js ومدير حزمة NPM الخاص به. Node.js هو وقت التشغيل
جافا سكريبت ، التي تتضمن بيئتها كل ما تحتاجه لتنفيذ برنامج ،
مكتوب في جافا سكريبت.
يمكنك تثبيته هنا . يجب اختيار نسخة "مستقرة" كما هو موضح في
قطة:

يمكنك أيضًا استخدام NVM (Node Version Manager) - إنها أداة ملائمة للتحكم في الإصدار Node.js. يمكنك تثبيته من المحطة الطرفية باستخدام الأمر:
env VERSION=`python tools/getnodeversion.py` make install DESTDIR=`nvm_version_path v$VERSION` PREFIX=""
ثم استخدم nvm * الإصدار * ، على سبيل المثال:
nvm use 10
الآن تم تثبيت Node.js ، يمكنك التحقق من ذلك باستخدام الأمر node -v:
node -v > 10.14.2
التالي يأتي MongoDB. يستخدم نظام إدارة قواعد البيانات (DBMS) ، المصنف كـ NoSQL ، مستندات مثل JSON ومخطط قاعدة بيانات.

لتثبيت ، تحتاج إلى تنفيذ سلسلة من الأوامر:
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4 echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list sudo apt-get update sudo apt-get install -y mongodb-org
عند تثبيت MongoDB ، يمكنك تشغيله في الخلفية مثل هذا:
sudo systemctl start mongod
Vue.js هو إطار أمامي لإنشاء واجهات المستخدم. تعتبر Vue مناسبة تمامًا لإنشاء تطبيقات ذات صفحة واحدة (SPA).
للعمل مع Vue.js ، هناك CLI (واجهة سطر الأوامر) رسمية - نظام متكامل للتطوير السريع على Vue.js. سيوفر الفرصة لإنشاء مشروع بشكل تفاعلي ، بالإضافة إلى توفير القدرة على التحديث والإعدادات المثالية للعمل مع الإطار. يمكنك تثبيته باستخدام NPM عن طريق تحديد علامة -g (العالمية) بحيث يتم تثبيت التبعية على مستوى العالم ويمكن استخدامها خارج مشروع محدد ، أي عالميا:
npm install -g @vue/cli
الآن بعد أن تم تثبيت DBMS MongoDB و Node.js + NPM ، يظل عليك تحديد محرر نصي. سأستخدم رمز VS كمحرر نص. يمكنك اختيار أي محرر حسب ذوقك: سواء كان Sublime أو Atom أو حتى Notepad ++.
تهيئة المشروع
لإنشاء تطبيق Vue.js جديد ، سوف نستخدم Vue CLI المثبت مسبقًا. يشبه أمر الإنشاء vue create * app_name *:
vue create mevn-app
تظهر واجهة في الجهاز تتيح لك تكوين إعدادات التطبيق الجديد. حدد "تحديد الميزات يدويًا" للحصول على إعدادات مفصلة ، وقم بعمل القائمة التالية:

في نهاية إنشاء التطبيق ، يجب أن تظهر رسالة مماثلة:

يمكنك بدء تشغيل التطبيق باستخدام الأمر npm run serve أعلاه ونرى ما الذي أنشأه Vue CLI:

تحتوي صفحة البداية هذه على وظيفة Vue Router (رابطان في الأعلى) ، ومكونات CLI المثبتة ، بالإضافة إلى روابط إلى الوثائق ، ومشروعات النظام البيئي Vue والشبكات الاجتماعية.
لذا ، يبدو التسلسل الهرمي للمشروع الذي تم إنشاؤه كما يلي:

- node_modules - دليل التبعيات المثبتة المطلوبة للمشروع للعمل. عادة ، لا يتم فهرستها في بوابة ، كما حجمها يصل أحيانا أحجام كبيرة جدا.
- package.json هو ملف تهيئة مشروع مرتبط بإحكام شديد بدليل node_modules. أنه يحتوي على معلومات حول المشروع (الاسم ، المؤلف ، الإصدار) ، ويتم تنفيذ البرامج النصية التي تعمل NPM ، وكذلك جميع التبعيات المثبتة المضمنة فقط في node_modules. يشار إلى التبعيات بالقيم الأساسية "التبعيات" (التبعيات المستخدمة في الإنتاج) و "التبعيات devDependities" (التبعيات المستخدمة في التطوير). أي هذا الملف ضروري بشكل أساسي حتى يمكن نشر المشروع على أي جهاز ، باستخدام الأمر npm i. يمكنك محاولة إزالة دليل node_modules ، ثم تشغيل الأمر npm i في جذر المشروع: سيتم سحب جميع التبعيات اللازمة المحددة في package.json مرة أخرى.
- package-lock.json هي لقطة من شجرة التبعية بأكملها. والحقيقة هي أن الحزم لها تبعيات المستوى الأعلى. عند التثبيت ، هذا ليس ملحوظًا ، ولكن يمكنك دائمًا رؤيته في package-lock.json. لذلك ، على سبيل المثال ، سوف تقوم حزمة bootstrap أثناء التثبيت بسحب حزمة jquery معها. لن يتم تحديد Jquery في package.json ، ولكن سيظل تثبيته بمثابة تبعية bootstrap ، أي ليس عليك تحديد مسج إضافي في "التبعيات" لكي يعمل bootstrap بشكل صحيح.
- babel.config.js هو ملف يحتوي على القواعد (الإعدادات المسبقة) والتي من خلالها يتعلم بابل كيفية ترجمة الشفرة. بابل هو رمز النقل. تحتوي لغة JavaScript على المواصفات التي يجب عليك اتباعها حتى تعمل الشفرة بشكل صحيح على الإنتاج. لكن غالبًا لا تتمكن جميع المتصفحات من تنفيذ مواصفات جديدة في المترجمين الفوريين ، وبعض المواصفات لا تطبق على الإطلاق. لهذا ، بابل موجود: إنه يترجم الشفرة من المواصفات إلى مواصفات يفهمها معظم المتصفحات. أي أثناء التطوير ، تكتب رمزًا واحدًا ، وبفضل بابل ، يذهب الآخر إلى الإنتاج. في حالتنا ، لا يوجد سوى إعداد مسبق واحد - "@ vue / app".
- postcss.config.js - ملف تكوين PostCSS. هذه أداة لمعالجة ما بعد CSS يمكنها تحويل CSS الخاص بك بعدة طرق رائعة ، على سبيل المثال ، إضافة البادئات تلقائيًا ، والتحقق من الامتثال لمعايير تصميم الكود ، وغيرها الكثير. يتم تثبيته تلقائيًا بواسطة Vue CLI ويحتوي حتى الآن على قواعد فقط لإضافة البادئات ، والتي ستضمن تطبيق المستعرض المتقاطع.
- Browserslist.rc - ملف يحدد المتصفحات التي تم تصميمها لتطوير التطبيقات. في حالتنا ، هذه هي آخر نسختين من المتصفحات التي تضم أكثر من 5٪ من المستخدمين في جميع أنحاء العالم ، باستثناء Internet Explorer دون الإصدار 8 الشامل.
- README.md - ملف به معلومات مشروع مكتوب في تخفيض السعر - لغة ترميزية خفيفة الوزن مصممة لكتابة النص الأكثر قابلية للقراءة وسهولة التحرير. عادةً ما يحتوي هذا الملف على وصف للمشروع ، ومعلومات حول إصدارات الحزم الرئيسية ، وإرشادات التثبيت ، إلخ.
- src (المصدر) - الدليل الذي يحدث داخله التطوير مباشرة. أنه يحتوي على جميع التعليمات البرمجية المكتوبة ، وكذلك الأصول / الدليل ، حيث يتم وضع scss / css ، js ، الخطوط ، الصور ، إلخ. يستخدم Vue.js Webpack لإنشاء: سيتم تجميع جميع التعليمات البرمجية الضرورية للتطبيق بشكل صحيح في ملف vendor.js واحد داخل dist / directory. يجدر إضافة هذا الدليل إلى .gitignor ، مثل يأخذ التطبيق المجمع مساحة إضافية في المستودع. مثل node_modules ، dist / يمكن تجميعها باستخدام أمر NPM واحد.
- عام - الدليل الذي يحتوي على قالب html الأساسي لإنشاء التطبيق النهائي ، وعادةً ما يكون رمزه (favicon.ico).
بداية التطوير (الواجهة الأمامية)
بما أننا نستخدم Vue CLI ، فبدلاً من تقسيم الشفرة إلى html و css و js منفصلة ، يتم إنشاء ملفات vue. لا يوجد شيء خارق حول هذا: ملفات vue تعني البنية التالية:
<template> * HTML * </template> <script> * JavaScript * </script> <style> * Stylesheet * </style>
يتم ذلك لتصميم مكونات Vue بشكل أكثر ملاءمة وهو مجرد سكر نحوي. هذه هي الملفات التي تمت معالجتها بواسطة Babel لإصدارها لاحقًا في الإنتاج.
في src / directory ، بالإضافة إلى مكونات Vue ، هناك أيضًا ملفات main.js و router.js.
في main.js ، يستورد Vue جميع الحزم اللازمة ، ثم ينشئ مثيل Vue جديد ويصعده في العنصر المحدد ، على مستوى DOM الظاهري ، باستخدام طريقة فئة Vue -. $ Mount ("# app"). داخل الطريقة ، يجب عليك تحديد سطر مع معرف عنصر html المحدد في قالب html الأساسي.
في router.js ، يستورد Vue حزمة vue-router التي قام Vue CLI بتثبيتها عند إنشاء المشروع وكافة المكونات المتضمنة في التوجيه. يحدث التوجيه عن طريق تمرير ، كحجة ، مجموعة من الكائنات إلى فئة جهاز التوجيه ، عند إنشاء مثيله:
new Router({ routes: [ { path: '/', name: 'home', component: Home }, ... ] )
أولاً ، دعنا نزيل أنماط Vue الافتراضية من App.vue. ثم يجب عليك حذف المكونات / الدليل مع HelloWorld.vue ، ولن تكون هناك حاجة إليها بعد الآن. بالإضافة إلى الدليل والمكون نفسه ، يجب إزالة الاستيراد الخاص به داخل طرق العرض / Home.vue ، حيث يتم استخدامه:
المشاهدات / الصفحة الرئيسية. <template> <div class="home"> <img alt="Vue logo" src="../assets/logo.png"> - <HelloWorld msg="Welcome to Your Vue.js App"/> </div> </template> <script> - import HelloWorld from '@/components/HelloWorld.vue' export default { name: 'home', components: { - HelloWorld } } </script>
الآن التطبيق يحتوي فقط على اثنين من الروابط وممثليهم. كما أن محتوى هذه الصفحات ليس ضروريًا ، ولكن ليس من الضروري حذفها ، يمكنك ببساطة تغييرها ، ولكن أولاً تحتاج إلى تحرير ملف التوجيه:
router.js: import Vue from 'vue' import Router from 'vue-router' import Home from './views/Home.vue' + import Thanks from './views/Thanks.vue' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'home', component: Home }, - { - path: '/about', - name: 'about', - component: () => import( './views/About.vue') - } + { + path: '/thanks', + name: 'thanks', + component: Thanks + } ] })
نمر الآن إلى المكونات ، بالاعتماد على نظام التوجيه. تحتاج إلى مكون شكر جديد. بدلاً من إنشاء واحدة جديدة ، قم بتعديل About.vue وأعد تسميتها Thanks.vue:
طرق عرض / About.vue> طرق عرض / شكرًا. <template> - <div class="about"> + <div class="thanks"> <h1>Thank you for your record!</h1> </div> </template>
وتغيير Home.vue: أضف نموذجًا يرسل بيانات مثل الاسم والبريد الإلكتروني والعنوان والجنس:
المشاهدات / الصفحة الرئيسية. <template> <div class="home"> - <img alt="Vue logo" src="../assets/logo.png"> + <form @submit.prevent="sendData"> + <div class="form-control"> + <label for="name">Name</label> + <input v-model="name" id="name" type="text"> + </div> + <div class="form-control"> + <label for="email">Email</label> + <input v-model="email" id="email" type="email"> + </div> + <div class="form-control"> + <label for="address">Address</label> + <input v-model="address" id="address" type="text"> + </div> + <div class="form-control"> + <label for="gender">Gender</label> + <span>Male <input v-model="gender" id="gender" type="radio" value="male"></span> + <span>Female <input v-model="gender" id="gender" type="radio" value="female"></span> + </div> + <input type="submit" class="send" value="Send"> + </form> </div> </template> <script> export default { name: 'home', - components: {} + data: function () { + return { + name: '', + email: '', + address: '', + gender: '', + + }, + methods: { + sendData() { + console.log(this.name, this.email, this.address, this.gender); + + } </script> + <style> + .form-control { + padding: 5px; + } + .form-control label { + display: block; + + .send { + margin: 5px + + </style>
أول شيء يمكن أن يكون مضللاً هو @ submit.prevent = "sendData". في Vue ، يتم سماع الأحداث باستخدام v-on: السمة ، ولكن بما أن هذه السمة تستخدم غالبًا أثناء التطوير ، فقد تم اختصار اختصارها ، @. أي يمكن تمثيل هذا السطر كـ v-on: submit.prevent = "sendData".
دعونا نرى ما يعنيه هذا عموما:
- يخبر v-on أو @ Vue بالاستماع إلى حدث ما ؛
- إرسال - هذا هو الحدث المحدد (إرسال قابل للتطبيق فقط على النماذج. للحصول على زر ، على سبيل المثال ، يمكنك تطبيق حدث النقرة والإدخال - الإدخال أو التغيير) ؛
- .prevent هو معدِّل الأحداث الذي يستدعي معالج js preventDefault () ، والذي يوقف حدث المستعرض مؤقتًا لعنصر - في حالتنا ، نموذج. يقوم حدث المستعرض الخاص بالنموذج بإرسال البيانات وإعادة تحميل الصفحة ، والتي يجب تجنبها. أيضا ، هناك بعض المعدلات مثل .stop (الإزالة الكاملة لحدث المتصفح) ، .once (تنفيذ الطريقة مرة واحدة فقط) وغيرها.
- sendData هي الطريقة (وظيفة داخل الكائن) التي سيتم استدعاؤها عند معالجة الحدث. يرجى ملاحظة أن الأقواس () للأسلوب يجب أن توضع فقط إذا قبلت المعلمات.
علاوة على ذلك ، في كل إدخال هناك سمة v- نموذج. وهو ثنائي الاتجاه يربط عناصر النموذج (الإدخال ، الاختيار ، textarea) مع البيانات. أي ، القيمة المكتوبة إلى الإدخال ، حيث v-model = "someText" ، ستتم كتابتها على الفور إلى خاصية dataText ، إذا كانت موجودة.
في الكائن المصدر ، نزيل خاصية المكونات ، لأن لن تحتوي Home.vue على مكونات تابعة ، لكننا نضيف طريقة البيانات. تحتوي البيانات على كائن بيانات Vue. تجدر الإشارة إلى أنه لا يمكنك فقط كتابة قيمة البيانات ككائن مع البيانات - أنت بالتأكيد بحاجة إلى كتابة القيمة كدالة ترجعها. هذه هي ميزة مكونات Vue.
في حالتنا ، فإن البيانات هي اسم قيم الإدخال والبريد الإلكتروني والعنوان والجنس.
بالإضافة إلى البيانات ، ظهرت خاصية أساليب تحتوي على جميع أساليب التعامل مع البيانات. هو مكتوب فيه طريقة واحدة فقط - sendData ، والذي ذكر أعلاه. إنه مرتبط بتقديم النموذج ويعرض الآن قيم الإدخال في وحدة التحكم.
والجزء الأخير من المكون هو الأسلوب. تتم كتابة الأنماط هنا بحيث يتم عرض النموذج بشكل صحيح.
دعنا نفتح تطبيقنا الآن أمامنا نموذج يجب ملؤه وإرسال البيانات باستخدام زر إرسال.


عند الإرسال ، لا يتم إعادة تحميل الصفحة ، ولا تتم إعادة تعيين قيم النموذج. حان الوقت للنظر في وحدة تحكم المتصفح (Ctrl + Shift + I):

إذا رأيت نفس الشيء في وحدة التحكم ، فقط مع القيم التي حددتها - تهانينا ، كتبت أول تطبيق Vue مكتمل. إذا لم يكن كذلك ، فعليك التحقق من صحة كل خطوة والتوصل إلى نتيجة إيجابية.
الآن ، دعنا نترك تطبيق Vue كما هو وانتقل إلى تطوير الخادم على Node.js بحيث يكون للتطبيق شيء لتبادل البيانات معه.
التطوير المستمر (الخلفية)
تحتاج أولاً إلى تثبيت حزم npm اللازمة لتشغيل الخادم:
npm install -S express morgan mongoose
يخبر رمز التبديل -S npm لإضافة هذه الحزم إلى package.json كعنصر في صفيف التبعيات. سيكون الإخراج رسالة مماثلة:

- Express.js هو إطار تطبيق ويب لـ Node.js مصمم لإنشاء تطبيقات الويب وواجهات برمجة التطبيقات. إنه أضيق الحدود ويتضمن عددًا كبيرًا من المكونات الإضافية.
- مورغان - حزمة لتسجيل طلبات HTTP إلى الخادم.
- Mongoose هو ORM (تعيين الكائنات العلائقية) لـ MongoDB المصنوع تحت Node.js.
ثم أضف دليلًا آخر إلى خادم جذر المشروع ، مع التسلسل الهرمي التالي:

server.js - سيكون هذا هو خادم Node.js ، والذي يتم إطلاقه باستخدام بيئة العقدة. يمكنك تجربة Node عن طريق كتابة رمز بسيط هنا ، على سبيل المثال:
الخادم / server.js console.log('Hello, world!');
ثم قم بتشغيل server.js باستخدام الأمر node من جذر المشروع ، مع تحديد المسار إلى الملف واسمه:
node server/server.js > Hello, world!
سنقوم بمسح الملف server.js وبدء التطوير. أولاً ، قم باستيراد جميع الحزم المثبتة مسبقًا (Express ، morgan و mongoose) ، وكذلك تهيئة تطبيق Express:
الخادم / server.js + const express = require('express'); + const mongoose = require('mongoose'); + const morgan = require('morgan'); + const path = require('path'); + + const app = express();
إذا لم تصادف const مطلقًا: const من قبل ، فقد جاء أحد عبارات التصريح المتغيرة (الثاني واسمحوا) ليحل محل var ، المعيار ES6. خصوصيتها هي أنه لا يمكن تغيير القيمة المخصصة للمتغير. للمتغيرات ذات القيم المتغيرة الإضافية ، يوصى باستخدام let.
require () هي وظيفة بيئة Node.js التي تنفذ القدرة على توصيل وحدات نمطية مختلفة ، كل من الأم و npm. لاحظ أننا لم نقم بتثبيت حزمة المسار ، لكننا نستوردها - تم تضمينها بالفعل في تبعيات البيئة.
التطبيق const = express () - تهيئة التطبيق Express. بعد ذلك ، سنعمل مع متغير التطبيق ، وسيكون هذا الخادم الخاص بنا.
بعد ذلك ، تحتاج إلى ضبط الإعدادات لتطبيق Express لدينا ، ولكن نظرًا لأنه صغير ، يلزمك تعيين معلمة واحدة فقط. خذ ، على سبيل المثال ، القيمة 3000 (أو أي منفذ متاح). بعد أن نبدأ الاستماع إلى المنفذ ، أي ابدأ الخادم:
الخادم / server.js ... + app.set('port', 3000); + + app.listen(app.get('port'), () => { + console.log(`[OK] Server is running on localhost:${app.get('port')}`); + });
تضيف طريقة المجموعة ببساطة الخاصية المحددة إلى الكائن المحدد بالقيمة المحددة ، والتي يمكن الحصول عليها عن طريق الوصول إلى اسم الخاصية باستخدام طريقة get. هذا هو بالضبط ما نفعله عندما نقوم بتعيين التطبيق للاستماع: app.get ('port') سيعود القيمة المحددة مسبقًا وهي 3000. بعد استلام المنفذ ، هناك وظيفة رد اتصال للسهم. إذا لم تصادف مطلقًا وظائف الأسهم من قبل: يتم الإشارة إلى وظيفة السهم على أنها () => {} وتشبه تقريبًا الدالة الكاملة () {} ، باستثناء واحدة: وظيفة السهم لها كائن عمومي كسياق للاتصال بالدالة (هذه) (عمومية) في بيئة Node.js ونافذة في بيئة المستعرض) ، والوظيفة المعتادة نفسها ، أي وظيفة. في هذه الحالة ، تبسط وظيفة السهم التسجيل ببساطة نحن لا نستخدم هذا بأي شكل من الأشكال. لذلك ، كدالة رد اتصال ، يتم تنفيذ رسالة ببساطة إلى وحدة التحكم تفيد بأن الخادم يعمل على المضيف المحلي: 3000. تتيح لك كتابة $ {...} داخل السلسلة إدراج قيمة محسوبة في هذه الحالة ، في حالتنا ، قيمة الإرجاع للدالة app.get ().
الآن ، افتح عنوان المضيف المحلي: 3000 في المستعرض الخاص بك ، سترى الرسالة "لا يمكن الحصول على /". هذا يعني أن خادمنا قد بدأ ويعمل بشكل صحيح. بعد ذلك ، سنجعل تطبيق Vue.js الخاص بنا يظهر بدلاً من هذه الرسالة ، لكن الآن سننشئ اتصالًا بقاعدة بيانات MongoDB والبرامج الوسيطة:
الخادم / server.js ... app.set('port', 3000); + + mongoose.connect('mongodb://localhost:27017/mevn-course', { useNewUrlParser: true }) + then(db => console.log('[OK] DB is connected')) + catch(err => console.error(err)); + + app.use(express.json()); + app.use(express.urlencoded({extended: false})); + app.use(morgan('dev')); ...
يتصل Mongoose.connect () بقاعدة البيانات. لاحظ أن MongoDB نفسه يجب أن يكون نشطًا قبل الاتصال به مرة أخرى. يتم تمرير معلمتين إلى هذه الطريقة - العنوان الأساسي ومجموعة من الإعدادات في شكل كائن. في حالتنا ، هذه هي السلسلة "mongodb: // localhost: 27017 / mevn-course" والكائن {useNewUrlParser: true}.
يستخدم useNewUrlParser للعمل مع إصدار MongoDB 3.1.0+. إذا كنت تستخدم إصدارًا أقل من 3.1.0 لسبب ما ، فيجب ألا تحدد هذه المعلمة.
. ثم و .catch هي الأساليب التي تُرجع الوعد عند الوفاء والفشل ، على التوالي. داخل هذه الطرق ، يتم استدعاء وظيفة رد الاتصال ، والتي تُرجع كائن قاعدة البيانات db كنتيجة لـ Promise for .then ، وخطأ لـ .catch. كلتا الطريقتين تطبعان المعلومات إلى وحدة التحكم: إما عن اتصال ناجح أو عن خطأ.
باستخدام app.use () ، يتم تثبيت الوسيطة لتطبيقنا. هذه هي الوظائف التي لها حق الوصول إلى كائن الطلب (req) ، وكائن الاستجابة (الدقة) ، ووظيفة المعالجة الوسيطة التالية (التالية) في دورة "طلب الاستجابة" للتطبيق. سوف نستخدم المحللون المضمنون في Express كبرنامج وسيط مع طلبات البيانات (في حالتنا ، json و urlencoded) وتثبيت حزمة morgan مسبقًا مع المعلمة 'dev' ، مما يعني تسجيل الدخول في وضع "التطوير". الآن يمكن للخادم تلقي البيانات الواردة مع الطلبات بتنسيق json و urlencoded وتسجيل جميع الطلبات الواردة. قم بتشغيل التطبيق مرة أخرى:
عقدة الخادم / server.js > [OK] Server is running on localhost:3000 > [OK] DB is connected
الآن ، إذا انتقلنا إلى المضيف المحلي: 3000 عنوان في المتصفح ، سيتم تسجيل جميع الطلبات في وحدة التحكم ، وفي هذه الحالة طلب GET:

سوف نشارك في تطوير نموذج السجل. يعد ذلك ضروريًا حتى يتم إرسال البيانات إلى قاعدة البيانات بالتنسيق المطلوب (يُسمى هذا التنسيق المخطط). يرسل نموذجنا من تطبيق Vue الاسم والبريد الإلكتروني والعنوان والجنس - كل هذا يمكن تمثيله كسلسلة. لذلك يجب أن يحتوي السجل في قاعدة البيانات على 4 حقول من النوع "صف". إنشاء نموذج:
الخادم / النماذج / Record.js + const mongoose = require('mongoose'); + const { Schema } = mongoose; + + const Record = new Schema({ + name: String, + email: String, + address: String, + gender: String, + }); + + module.exports = mongoose.model('Record', Record);
نقوم باستيراد حزمة mongoose وتعيين متغير المخطط إلى قيمة فئة المخطط من حزمة mongoose. يُطلق على الترميز "const {Schema} = mongoose" التدمير في ES6 ويعادل "const Schema = mongoose.Schema". بعد ذلك ، يتم إنشاء مثيل لفئة المخطط ، والمعلمة هي كائن له أسماء خصائص السجل وأنواع البيانات الخاصة به.
"Module.exports = ..." هو إدخال تصدير. أي عندما نستورد هذه الوحدة ، ستكون نتيجة الاستيراد mongoose.model ('سجل' ، سجل).
عند إنشاء النموذج ، ستحتاج إلى إنشاء ملف توجيه API. كأسلوب معماري للتفاعل المكون ، سيتم استخدام REST.
يعرّف REST API مجموعة من الوظائف التي يمكن للمطورين من خلالها تقديم طلبات وتلقي الإجابات. التفاعل يحدث عبر بروتوكول HTTP. أساليب استدعاء واجهة برمجة تطبيقات REST هي منهجية CRUD (إنشاء ، قراءة ، تحديث ، حذف) ، أي الحصول ، وظيفة ، وضع ، حذف. أضف الكود إلى ملف التوجيه:server / models / Record.js + const express = require('express'); + const router = express.Router(); + + const Record = require('../models/Record'); + + router.get('/', async (req, res) => { + res.json(await Record.find()); + }); + + router.post('/', async (req, res) => { + const record = new Record(req.body); + await record.save(); + res.json({state: 'success'}); + }); + + router.get('/:id', async (req, res) => { + res.json(await Record.findById(req.params.id)); + }); + + router.put('/:id', async (req, res) => { + await Record.findByIdAndUpdate(req.params.id, req.body); + res.json({state: 'updated'}); + }); + + router.delete('/:id', async (req, res) => { + await Record.findByIdAndRemove(req.params.id); + res.json({state: 'deleted'}); + }); + + module.exports = router;
نقوم باستيراد الحزمة Express وإنشاء كائن جهاز التوجيه. نحن أيضا استيراد وحدة نمطية السجل للتفاعل مع قاعدة البيانات. ما يلي ببساطة يصف التوجيه. يعتبر الإنشاء غير المتزامن / الانتظار طريقة جديدة نسبيًا لكتابة التعليمات البرمجية غير المتزامنة. سابقًا ، تم كتابة رمز مشابه باستخدام وظائف رد الاتصال والوعود. بفضل عدم التزامن / الانتظار ، تصبح التعليمات البرمجية غير المتزامنة مماثلة لتلك المتزامنة ، وتظهر ميزات سلوكها في مثل هذه التعليمات البرمجية ، وهي مفيدة للغاية في بعض المواقف التي تكون فيها الوعود باستخدامها غير ملائمة لأسباب مختلفة.بدلا من ذلك: router.get('/', req, res) => { res.json(Record.find() .then((data) => { return data; })); });
لدينا: router.get('/', async (req, res) => { res.json(await Record.find()); });
router , .get(), .post(), .put() .delete() , . callback- req — res — . , POST, , Record, , find(), findById(), findByIdAndUpdate(), findByIdAndRemove(). JSON, , res.json({state: 'success'}). POST -: Record, , Vue-, , save(), JSON. , : get, put delete — :id. , , “/”, , req.params.id , . id.
ربما يكون السؤال الذي يطرح نفسه ، أي معرف سنقوم بالوصول إلى السجلات في قاعدة البيانات إذا كان المخطط يحتوي فقط على اسم الحقول والبريد الإلكتروني والعنوان والجنس؟ الإجابة: ينشئ MongoDB نفسه معرفًا لكل سجل ، وسيتم تسميته _id.تتم كتابة النموذج والتوجيه ، يبقى فقط لاستيراد الوحدة النمطية المطلوبة إلى server.js:server / server.js ... app.use(morgan('dev')); + + app.use('/api/records', require('./routes/records'));
, /api/records. ., POST- , (, email, )
localhost :3000/api/records.
— API. Postman. API.
GET-
localhost :3000/api/records :

POST- , :

, JSON, ,
{"الدولة": "النجاح"}. نقوم بتنفيذ طلب GET السابق مرة أخرى:
كل شيء تم إيقافه ، يمكنك اختبار العمليات المتبقية بشكل مستقل على البيانات (UPDATE أو DELETE أو GET one).وصل تطوير الجزء الخلفي إلى نهايته ، إلا أنه يبقى لجعل اللمسة النهائية - تعيين الملفات الثابتة لعرضها في المضيف المحلي : 3000 /. أضف الكود:server / server.js ... app.use('/api/records', require('./routes/records')); + app.use('/', express.static(path.join(__dirname, '../dist')));
التطوير المستمر (الواجهة الأمامية)
بالعودة إلى تطبيق Vue ، يوجد الآن واجهة برمجة تطبيقات يمكنه التفاعل معها. لذلك ، دون إضاعة الوقت ، سنقوم بتغيير طريقة إرسال البيانات المكتوبة مسبقًا ، ولكن أولاً ، باستخدام npm ، قم بتثبيت حزمة axios - npm i -S axios.وجهات النظر / الصفحة الرئيسية ... <script> + import axios from 'axios'; ... methods: { + async sendData() { - console.log(this.name, this.email, this.address, this.gender); + console.log(await axios({ + url: 'http://localhost:3000/api/records', + method: 'post', + data: { + name: this.name, + email: this.email, + address: this.address, + gender: this.gender + + })); } }
Axios هي مكتبة عميل لإرسال الطلبات إلى خادم يستخدم الوعود الافتراضية. نحن هنا نستخدم بنية المزامنة / الانتظار المألوفة. يتم تمرير كائن إلى وظيفة axios - مجموعة من الخيارات (عنوان url ، الطريقة ، البيانات). عند تنفيذ الطريقة ، يتم إرسال الطلب.الآن قم بتشغيل الأمر npm run build. باستخدامه ، سيقوم Vue بتجميع التطبيق النهائي في دليل dist ، والذي حددناه كملفات ثابتة للخادم: npm run build
ثم نعيد تشغيل الخادم وفي المتصفح نذهب إلى المضيف المحلي : 3000 /. بالضبط ، الآن يتم عرض تطبيق Vue لدينا هنا. ملء النموذج وإرسال البيانات عن طريق النقر فوق إرسال. ننظر إلى وحدة التحكم:
يتم إرجاع استجابة الخادم كبيانات. هذا يعني أنه تمت إضافة السجل ، وأن تطبيقنا يعمل كما ينبغي.الآن سنجعل اللمسات الأخيرة في التطبيق: إعادة التوجيه عند إرسال النموذج إلى صفحة الشكر ؛ القدرة على الانتقال من صفحة الشكر إلى الصفحة الرئيسية ، وحذف روابط navbar ، وحذف console.log ():views / Thanks.vue <template> <div class="thanks"> <h1>Thank you for your record!</h1> + router-link to="/">Home</router-link> </div> </template>
وجهات النظر / الصفحة الرئيسية ... async sendData() { - console.log(await axios({ + await axios({ url: 'http://localhost:3000/api/records', method: 'post', data: { name: this.name, email: this.email, address: this.address, gender: this.gender } - })); + }); + this.$router.push('thanks'); } ...
App.vue ... <div id="app"> - <div id="nav"> - <router-link to="/">Home</router-link> | - <router-link to="/thanks">About</router-link> - </div> <router-view/> </div> ...
تطبيق Vue الخاص بنا جاهز تمامًا ، حيث نقوم بتجميعه باستخدام npm run build ، نعيد تشغيل الخادم ، نتحقق من قابلية التشغيل.اكتمال التطوير (الخلفية)
سيكون من الجميل أن يرسل الخادم إشعارًا عبر البريد الإلكتروني عندما يضيف العميل كل سجل جديد إلى قاعدة البيانات. للقيام بذلك ، سوف نستخدم الخدمة لإرسال رسائل إلى Node.js - Nodemailer. تثبيته: npm install -S nodemailer. الآن بعد تثبيت Nodemailer ، أضف وظيفة إلى server.js: server / route/ records.js ... const router = express.Router(); + const nodemailer = require('nodemailer'); ... router.post('/', async (req, res) => { const record = new Record(req.body); await record.save(); + const output = ` + <p>You have a new message from MEVN-course:</p> + <ul> + <li>name: ${req.body.name}</li> + <li>email: ${req.body.email}</li> + <li>address: ${req.body.address}</li> + <li>gender: ${req.body.gender}</li> + </ul> + `; + let transporter = nodemailer.createTransport({ + host: 'smtp.gmail.com', + port: 587, + secure: false, + auth: { + user: 'your_email@gmail.com', + pass: 'your_password' + + }); + let mailOptions = { + from: '"MEVN-course " <your_email@gmail.com>', + to: 'some_email@gmail.com', + subject: `MEVN-course | New message`, + text: req.body.name, + html: output + }; + transporter.sendMail(mailOptions, (error, info) => { + if (error) { + return console.log(error); + + console.log('Message sent: %s', info.messageId); + console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info)); + }); res.json({state: 'success'}); });
, . -, nodemailer. -, post , , . output, html-. transporter, createTransport nodemailer, — : , , . , Gmail, , Gmail-. mailOptions, — : , , . , sendMail transporter, .
نحن إعادة تشغيل الخادم والاختبار. إذا كانت معلومات المصادقة صحيحة ، وكانت إعدادات الحساب تسمح باستخدام صندوق البريد من قبل تطبيقات الطرف الثالث ، فسيتم إرسال الرسالة وسيتم إرسال رسالة إلى وحدة التحكم حول الإرسال الناجح ، وإذا لم يكن الأمر كذلك ، فسيتم الإشارة إلى الخطأ في وحدة التحكم. يبدو كأنه إرسال ناجح:
وهكذا فهو غير ناجح:
يؤدي
على هذا تطوير التطبيق وصل إلى نهايته. ماذا لدينا:- خبرة في تطوير تطبيقات Vue ؛
- خبرة في تطوير خادم Node + Express ؛
- تجربة مع MongoDB ؛
- تجربة مع npm ؛
- القدرة على تنظيم صفحات إعادة التوجيه ؛
- القدرة على تنظيم النشرات الإخبارية عبر البريد الإلكتروني من الخادم ؛
- القدرة على إرسال من العميل وتلقي طلبات المتشعب على الخادم ؛
- فهم CRUD و REST API ؛