جاري التحميل...
جاري التحميل...
بناء تطبيق كامل يجمع كل المفاهيم
مرحبًا بك في الدرس الأخير من مرحلة جافاسكريبت + ES6+! في هذا الدرس، سنبني مشروعًا عمليًا يجمع جميع المفاهيم التي تعلمتها في الدروس السابقة.
💡 مشروعنا::
نظام إدارة طلاب يحتوي على بيانات الطلاب ومعدلاتهم. سنبني دوالًا لإضافة الطلاب وحساب المعدلات والتصفية وعرض التقارير.
هذا المشروع مصمم ليكون جسرًا بين أساسيات جافاسكريبت ومكتبة React. كل مفهوم تستخدمه هنا ستجده مباشرة في React:
من خلال هذا المشروع، ستطبق عمليًا:
في المشاريع الحقيقية، نقسم الكود إلى ملفات منفصلة. لأغراض تعليمية، سنكتب كل شيء في ملف واحد، ثم نُظهر كيف يمكن تقسيمه.
المبدأ الأساسي: كل ملف مسؤول عن مهمة واحدة فقط (مبدأ المسؤولية الفردية).
الخطوة الأولى هي تعريف شكل البيانات التي سيعمل معها مشروعنا. نستخدم مصفوفة كائنات، النمط الأكثر شيوعًا لتمثيل مجموعات البيانات في جافاسكريبت.
الآن نبني الدوال الأساسية: حساب المتوسط باستخدام reduce، وتصنيف الدرجات، وثراء بيانات الطلاب.
حساب المتوسط مع reduce: دالة reduce من أقوى طرق المصفوفات. تأخذ دالة callback وقيمة أولية، ثم تكرر عبر كل عنصر متراكمًا النتيجة.
ثراء البيانات مع map و Spread: بعد حساب المتوسط، نستخدم map لإنشاء نسخة محسّنة لكل طالب. نستخدم عملية Spread لإضافة حقول جديدة دون تعديل الكائن الأصلي.
الآن نبني دوالًا تبحث وتصفية البيانات. هذه هي أساس كل تطبيق ويب: البحث والتصفية والتحقق الشرطي.
مقارنة الطرق:
الآن نجمع كل الدوال في نظام متكامل: إحصائيات عامة، وتقارير تفصيلية، وإدارة البيانات (إضافة وحذف وتحديث).
إدارة البيانات (CRUD): إنشاء (إضافة)، قراءة (عرض)، تحديث (تعديل)، حذف (إزالة). لاحظ أننا لا نعدّل المصفوفة الأصلية أبدًا - ننشئ نسخ جديدة، وهو مبدأ أساسي في React.
هذا هو الكود الكامل لنظام إدارة الطلاب. يمكنك نسخه وتشغيله مباشرة في محرر جافاسكريبت.
تقسيم الكود إلى وحدات: في المشاريع الحقيقية، لا نكتب كل شيء في ملف واحد. كل ملف مسؤول عن مهمة محددة. تسمى برمجة الوحدات.
محاكاة غير المتزامنة: في التطبيقات الحقيقية، تأتي البيانات من خادم عبر الشبكة. نستخدم async/await مع الوعود للتعامل مع هذا التأخير.
وقت التحديات! حاول حل هذه التحديات لتثبيت ما تعلمته.
أي مفهوم سنستخدمه لحساب معدل مجموعة من الدرجات في مصفوفة؟
جرب هذه التحديات: 1. ترتيب حسب المتوسط، 2. تجميع حسب القسم، 3. تصدير CSV، 4. التحقق من الدرجات، 5. بحث متقدم.
الحل:
// تحدي 1: ترتيب الطلاب
const sortByAverage = (studentsList) => {
return [...studentsList].sort((a, b) => b.average - a.average);
};
// تحدي 2: تجميع حسب القسم
const groupByDepartment = (studentsList) => {
return studentsList.reduce((groups, student) => {
const key = student.department;
if (!groups[key]) groups[key] = [];
groups[key].push(student);
return groups;
}, {});
};
// تحدي 3: تصدير CSV
const exportToCSV = (studentsList) => {
const header = "الاسم,المعدل,التسمية,القسم";
const rows = studentsList.map(s =>
`${s.name},${s.average},${s.gradeLabel},${s.department}`
);
return [header, ...rows].join("\n");
};
// تحدي 4: التحقق من الدرجات
const validateGrades = (studentsList) => {
return studentsList.flatMap((student, si) =>
student.grades
.map((grade, gi) => ({ student: student.name, gradeIndex: gi, grade }))
.filter(g => g.grade < 0 || g.grade > 100)
.map(g => ({ ...g, error: g.grade > 100 ? "الدرجة أعلى من 100" : "الدرجة أقل من 0" }))
);
};
// تحدي 5: البحث المتقدم
const advancedSearch = (studentsList, criteria) => {
return studentsList.filter(s => {
if (criteria.name && !s.name.includes(criteria.name)) return false;
if (criteria.department && !s.department.includes(criteria.department)) return false;
if (criteria.status && s.status !== criteria.status) return false;
if (criteria.minAverage && s.average < criteria.minAverage) return false;
return true;
});
};ثراء البيانات
calculateAverage(grades) باستخدام reduce | getGradeLabel(average) باستخدام if/else | enrichStudent(student) باستخدام spread
البحث والتصفية
getActiveStudents() باستخدام filter | getTopStudents() باستخدام filter | findByName() باستخدام find | searchStudents() باستخدام filter مع includes
الإحصائيات
getStatistics() باستخدام reduce لبناء كائن إحصائيات كامل مع count و average و highest و lowest و active
إدارة البيانات
addStudent() باستخدام spread | removeStudent() باستخدام filter | updateGrades() باستخدام map مع spread
أنماط غير المتزامنة
fetchStudentsFromAPI() باستخدام Promise | async/await مع try/catch/finally | processStudentData() تجمع map و reduce و async