تطبيقات الويب التقدّمية: IndexedDB

1. مرحبًا

في هذا التمرين العملي، ستتعرّف على كيفية الاحتفاظ بنسخة احتياطية من بيانات العميل واستردادها إلى IndexedDB. هذا هو الدرس التطبيقي الثالث في سلسلة من دروس الترميز المصاحبة لورشة عمل تطبيقات الويب التقدّمية. كانت تجربة الترميز السابقة بعنوان العمل باستخدام Workbox. تتضمّن هذه السلسلة خمسة دروس برمجية أخرى.

أهداف الدورة التعليمية

  • إنشاء قاعدة بيانات IndexedDB ومخزن عناصر باستخدام idb
  • إضافة عناصر إلى مخزن كائنات واسترجاعها منه

ما يتعين عليك معرفته

  • ‫JavaScript وPromises

المتطلبات

2. إكمال الإعداد

ابدأ إما باستنساخ الرمز الأولي أو تنزيله لإكمال هذا الدرس التطبيقي حول الترميز:

إذا نسخت المستودع، تأكَّد من أنّك تستخدم الفرع pwa03--indexeddb. يحتوي ملف ZIP أيضًا على الرمز الخاص بهذا الفرع.

يتطلّب هذا الرمز الأساسي الإصدار 14 من Node.js أو إصدارًا أحدث. بعد توفّر الرمز، شغِّل npm ci من سطر الأوامر في مجلد الرمز لتثبيت جميع الملفات التابعة التي ستحتاج إليها. بعد ذلك، شغِّل npm start لبدء خادم التطوير الخاص بتجربة البرمجة.

يقدّم ملف README.md لرمز المصدر شرحًا لجميع الملفات الموزّعة. بالإضافة إلى ذلك، إليك الملفات الرئيسية الحالية التي ستعمل عليها خلال هذا الدرس العملي:

الملفات الرئيسية

  • js/main.js: ملف JavaScript الرئيسي للتطبيق

3- إعداد قاعدة البيانات

قبل استخدام قاعدة بيانات IndexedDB، يجب فتحها وإعدادها. على الرغم من إمكانية إجراء ذلك مباشرةً، إلا أنّه نظرًا لأنّ IndexedDB تم توحيدها قبل أن تصبح Promises بارزة، يمكن أن تكون واجهة المستند إلى معاودة الاتصال غير عملية للاستخدام. بدلاً من ذلك، سنستخدم idb، وهو برنامج تضمين Promise صغير جدًا لـ IndexedDB. للبدء، عليك أولاً استيرادها إلى js/main.js:

import { openDB } from 'idb';

بعد ذلك، أضِف رمز الإعداد التالي إلى أعلى أداة معالجة الحدث DOMContentLoaded:

// Set up the database
const db = await openDB('settings-store', 1, {
  upgrade(db) {
    db.createObjectStore('settings');
  },
});

الشرح

هنا، يتم إنشاء قاعدة بيانات IndexedDB باسم settings-store. يتم ضبط إصدارها على 1 ويتم تهيئتها باستخدام مخزن كائنات يُسمّى settings. هذا هو أبسط أنواع مستودعات الكائنات، وهو عبارة عن أزواج بسيطة من المفاتيح والقيم، ولكن يمكن إنشاء مستودعات كائنات أكثر تعقيدًا حسب الحاجة. بدون عملية تهيئة وحدة تخزين العناصر هذه، لن يكون هناك مكان لوضع البيانات فيه، لذا فإنّ حذفها هنا سيكون مثل إنشاء قاعدة بيانات بدون جداول.

4. حفظ حالة المحرّر عند التعديل

بعد إعداد قاعدة البيانات، حان الوقت لحفظ المحتوى فيها. يعرض المحرِّر طريقة onUpdate تتيح لك تمرير دالة يتم استدعاؤها كلما تم تعديل المحتوى في المحرِّر. وهو المكان المثالي لإدخال التغييرات وإضافتها إلى قاعدة البيانات. لإجراء ذلك، أضِف الرمز التالي قبل تعريف defaultText مباشرةً في js/main.js:

// Save content to database on edit
editor.onUpdate(async (content) => {
  await db.put('settings', content, 'content');
});

الشرح

db هي قاعدة بيانات IndexedDB التي تم فتحها سابقًا. تسمح طريقة put بإنشاء أو تعديل الإدخالات في مخزن الكائنات في قاعدة البيانات هذه. الوسيطة الأولى هي مخزن العناصر في قاعدة البيانات المطلوب استخدامها، والوسيطة الثانية هي القيمة المطلوب تخزينها، والوسيطة الثالثة هي المفتاح المطلوب حفظ القيمة فيه إذا لم يكن واضحًا من القيمة (في هذه الحالة، لا يكون واضحًا لأنّ قاعدة البيانات لا تتضمّن مفاتيح محدّدة). بما أنّها غير متزامنة، يتم تضمينها في async/await.

5- استرداد الحالة عند التحميل

أخيرًا، لاسترداد عمل المستخدم الجاري، يجب تحميله عند تحميل المحرّر. يوفّر المحرّر طريقة setContent لتنفيذ ذلك، أي لضبط محتواه. يتم استخدامها حاليًا لضبطها على قيمة defaultText. عدِّله باستخدام ما يلي لتحميل عمل المستخدم السابق بدلاً من ذلك:

editor.setContent((await db.get('settings', 'content')) || defaultText);

الشرح

بدلاً من ضبط قيمة المحرّر على defaultText فقط، يحاول الآن الحصول على المفتاح content من مخزن الكائنات settings في قاعدة بيانات settings-store IndexedDB. إذا كانت هذه القيمة متوفّرة، يتم استخدامها. وإذا لم يتوفّر، سيتم استخدام النص التلقائي.

6. ضبط حالة "الوضع الليلي" واستردادها

بعد أن أصبحت معتادًا على IndexedDB، أضِف الرمز التالي إلى أسفل js/main.js وعدِّله لحفظ إعدادات الوضع الداكن المفضّلة لدى المستخدم عند تغييرها، وتحميل هذه الإعدادات عند بدء الوضع الداكن.

// Set up night mode toggle
const { NightMode } = await import('./app/night-mode.js');
new NightMode(
  document.querySelector('#mode'),
  async (mode) => {
    editor.setTheme(mode);
    // Save the night mode setting when changed
  },
  // Retrieve the night mode setting on initialization
);

7. تهانينا!

لقد تعلّمت كيفية حفظ البيانات وتحميلها من مخزن عناصر في IndexedDB.

رمز التدريب التالي في السلسلة هو من علامة التبويب إلى شريط المهام