القوائم المنسدلة الضخمة في واجهات الإدارة: لماذا تُبطئك
القوائم المنسدلة الضخمة في واجهات الإدارة تبطئ النماذج، تُربك المستخدمين، وتجهد الـ APIs. تعرّف على البحث typeahead، التصفية على الخادم، وأنماط بيانات مرجعية نظيفة.

المشكلة الحقيقية مع القوائم المنسدلة الضخمة
تنقر على حقل، تفتح القائمة المنسدلة، ثم تتردد الأشياء. الصفحة تتلعثم للحظة، التمرير يبدو لزجًا، وتفقد موضعك. حتى لو استغرق ذلك ثانية واحدة فقط، فإنه يكسر إيقاع ملء النموذج.
هذا يظهر غالبًا في لوحات الإدارة والأدوات الداخلية لأنها تتعامل مع مجموعات بيانات حقيقية وفوضوية: عملاء، طلبات، SKUs، تذاكر، مواقع، موظفين. التطبيقات العامة أحيانًا تستطيع تقييد الخيارات. أدوات الإدارة غالبًا تحتاج الوصول إلى كل شيء، وهذا يحول عنصر تحكم بسيط في النموذج إلى مستعرض بيانات مصغر.
ما يُعد "كبيرًا" يعتمد على السياق، لكن الألم يبدأ عادةً أبكر مما يتوقع الناس. المئات من الخيارات لا تزال قابلة للاستخدام، لكن المسح يصبح بطيئًا وتزداد الأخطاء بالنقر. عند الآلاف يبدأ المستخدمون بالشعور بالتأخير وإجراء المزيد من الاختيارات الخاطئة. عند عشرات الآلاف، يتوقف التحكم عن التصرف كقائمة منسدلة ويبدأ بالتصرف كخلل في الأداء. عند الملايين، لا يمكن أن يكون قائمة منسدلة إطلاقًا.
المشكلة الحقيقية ليست السرعة فقط. إنها الدقة.
عندما يتصفح الناس قوائم طويلة، يختارون "John Smith" الخاطئ، أو "Springfield" الخاطئ، أو متغير المنتج الخطأ، ثم يحفظون بيانات سيئة. الكلفة تظهر لاحقًا كعمل دعم، وإعادة تحرير، وتقارير لا يثق بها أحد.
الهدف بسيط: إبقاء النماذج سريعة ومتوقعة دون فقدان الدقة. هذا يعني عادةً استبدال "تحميل كل شيء والتمرير" بأنماط تساعد الناس على العثور على السجل الصحيح بسرعة، بينما يجلب النظام فقط ما يحتاجه.
من أين تأتي البطء (بعبارات بسيطة)
القائمة المنسدلة الضخمة تبدو بسيطة، لكن المتصفح يتعامل معها كعمل حقيقي. عندما تُحمِّل آلاف العناصر، فإنك تطلب من الصفحة إنشاء آلاف عناصر option، وقياسها، ورسمها على الشاشة. تكلفة DOM والرسم تتراكم بسرعة، خاصة عندما يحتوي النموذج على عدة حقول مثل هذا.
يمكن أن يبدأ البطء قبل أن يُرى أي شيء. العديد من واجهات الإدارة تقوم بتحميل قوائم مرجعية مسبقًا (عملاء، منتجات، مواقع) حتى تفتح القائمة بسرعة لاحقًا. هذا يعني استجابات API أكبر، ووقت أكثر للانتظار على الشبكة، ووقت أكثر لتحليل JSON. حتى على اتصال جيد، تؤخر الحمولات الكبيرة اللحظة التي يصبح فيها النموذج قابلاً للتفاعل.
ثم هناك الذاكرة. الاحتفاظ بقوائم كبيرة في المتصفح يستهلك RAM. على الحواسيب منخفضة المواصفات، المتصفحات القديمة، أو عندما تكون التبويبات مشغولة، قد يسبب هذا تلعثمًا، بطءًا في الكتابة، أو حتى تجميدًا مؤقتًا عند فتح القائمة.
المستخدمون لا يهتمون بالسبب التقني. يلاحظون التوقفات. "التأخيرات الصغيرة" الشائعة هي التي تكسر التدفق:
- الصفحة تُحمَّل، لكن النقر الأول لا يفعل شيئًا للحظة.
- فتح القائمة يتأخر، أو التمرير يبدو متقطعًا.
- الكتابة في حقول أخرى تصبح متأخرة قليلاً.
- الحفظ يبدو أبطأ لأن الواجهة تحت حمل بالفعل.
تأخر 300 إلى 600 مللي ثانية لا يبدو كثيرًا، لكن متكررًا عبر يوم من إدخال البيانات يصبح إحباطًا حقيقيًا.
مشاكل تجربة المستخدم: ليست مجرد أداء
القوائم المنسدلة الكبيرة لا تبدو بطيئة فقط. إنها تحول خيارًا بسيطًا إلى لغز صغير، ويُكلّف المستخدمين هذا في كل مرة يملؤون النموذج.
لا يستطيع الناس مسح 2000 عنصر بشكل فعال. حتى لو حملت القائمة فورًا، تُجبر العين على وضع "البحث": تمرير، تجاوز الهدف، الرجوع، الشك بالنفس. كلما كبرت القائمة، قضى المستخدمون وقتًا أطول في التأكد من اختيارهم الصحيح بدلًا من إكمال المهمة.
الاختيارات الخاطئة سهلة الحدوث أيضًا. تمريرة صغيرة على لوحة اللمس يمكنها تحريك الخيار المظلّل، ونقرة تُسقط على الصف الخطأ. الخطأ يظهر غالبًا لاحقًا (فاتورة خاطئة، مستودع خاطئ، فئة خاطئة)، مما يخلق عملًا إضافيًا ومسارات تدقيق فوضوية.
بحث الـ select الأصلي فخ آخر. على بعض المنصات، الكتابة تقفز إلى العنصر التالي الذي يبدأ بتلك الحروف. على أخرى يتصرف بشكل مختلف أو لا يكون قابلًا للاكتشاف. المستخدمون يلومون تطبيقك، رغم أن التحكم يتصرف كقائمة بسيطة.
القوائم الطويلة تخفي أيضًا مشاكل جودة البيانات. التكرارات، التسميات غير الواضحة، السجلات القديمة التي يجب أرشفتها، والخيارات التي تختلف بلاحقة فقط تصبح غير مرئية في الضجيج.
فحص واقعي سريع لأي حقل "اختر واحد":
- هل سيختار زميل جديد بشكل صحيح من المحاولة الأولى؟
- هل هناك أسماء قريبة من بعضها تشجع الأخطاء؟
- هل يتصرف التحكم نفسه على Mac وWindows وMobile؟
- إذا كان الاختيار خاطئًا، هل سيلاحظه أحد فورًا؟
متى تبقى القائمة المنسدلة الخيار الصحيح
ليست كل حقول الاختيار بحاجة بحث. تصبح القوائم المنسدلة مؤلمة عندما تكون القائمة طويلة، تتغير كثيرًا، أو تعتمد على السياق. لكن مجموعة صغيرة وثابتة من الخيارات هي بالضبط ما تجيده القوائم.
القائمة المنسدلة اختيار قوي عندما يستطيع الناس مسحها بسرعة والتعرّف على القيمة الصحيحة دون تفكير. فكر في حقول مثل حالة الطلب، الأولوية، دور المستخدم، أو البلد. إذا بقيت القائمة تقريبًا نفسها بمرور الوقت وعادة ما تتسع لشاشة واحدة، فإن التحكم البسيط يفوز.
لا تزال القائمة المنسدلة الأداة المناسبة عندما تكون الخيارات ثابتة، سهلة التعرف، ومشتركة عبر المستخدمين. إذا كانت القائمة عادةً تحت حوالي 50 إلى 100 عنصر ويختار الناس بالقراءة بدلًا من الكتابة، ستحصل على السرعة والوضوح.
راقب اللحظة التي يبدأ فيها المستخدمون بكتابة نفس الحروف الأولى مرارًا وتكرارًا. هذه إشارة أن القائمة غير قابلة للتذكر، وأن المسح أصبح أبطأ من البحث.
نقطة توقف صارمة هي أي قائمة تتغير كثيرًا أو تعتمد على من قام بتسجيل الدخول. "Assigned to" غالبًا يعتمد على الفريق، المنطقة، والصلاحيات. قائمة تحميل كل المستخدمين ستكون قديمة وثقيلة ومربكة.
إذا كنت تبني هذا في أداة مثل AppMaster، قاعدة جيدة هي: احتفظ بالقوائم المنسدلة للبيانات المرجعية الصغيرة (مثل الحالات)، وانتقل إلى اختيار يعتمد على البحث لأي شيء ينمو مع عملك (عملاء، منتجات، موظفون).
Typeahead: أبسط بديل
الـ typeahead (غالبًا يسمّى autocomplete) هو حقل نصي يبحث أثناء الكتابة ويعرض قائمة قصيرة من النتائج المطابقة. بدلًا من إجبار الناس على التمرير عبر قائمة ضخمة، تسمح لهم باستخدام لوحة المفاتيح والاختيار من نتائج تتحدث في الوقت الحقيقي.
هذا عادةً أفضل إصلاح أولي لأنه يقلل ما تعرضه، يقلل ما تنزّله، ويقلل الجهد المطلوب للعثور على العنصر الصحيح.
Typeahead جيد يتبع بعض القواعد الأساسية. ينتظر عددًا أدنى من الحروف قبل البحث (غالبًا 2 إلى 3) حتى لا يهتز الواجهة على "a" و"e". يعيد النتائج بسرعة ويحتفظ بالقائمة قصيرة (غالبًا أعلى 10 إلى 20 تطابقًا). يُبرِز الجزء المطابق من كل نتيجة حتى يكون المسح سريعًا. كما يكون واضحًا بشأن الحالات الفارغة، برسالة مباشرة "لا توجد نتائج" وخطوة مقترحة.
سلوك لوحة المفاتيح أهم مما يظن الناس: الأسهم للأعلى والأسفل يجب أن تتحرك عبر الخيارات، Enter يختار، وEsc يغلق. إذا كانت هذه الأساسيات مفقودة، قد يشعر الـ typeahead بأنه أسوأ من القائمة المنسدلة.
تفاصيل صغيرة تحافظ على الشعور بالثبات. حالة تحميل خفيفة تمنع الكتابة المزدوجة والارتباك. إذا كتب شخص "jo" وتوقف، يجب أن تظهر النتائج سريعًا. إذا كتب "john sm" يجب أن تضيق القائمة دون القفز أو فقدان الخيار المظلّل.
مثال: في لوحة إدارة تختار عميلًا، كتابة "mi" يمكن أن تظهر "Miller Hardware" و"Mina Patel" و"Midtown Bikes" مع تمييز جزئية "mi". في AppMaster، هذا النمط مناسب لأن واجهتك يمكنها استدعاء نقطة نهاية تبحث في العملاء وتُعيد فقط المطابقات القليلة التي تحتاجها، لا الجدول كله.
عندما لا توجد تطابقات فعلية، كن مباشرًا ومفيدًا: "لم يتم العثور على عملاء لـ 'johns'. جرّب اسمًا أقصر أو ابحث بالبريد الإلكتروني."
كيف تنفذ typeahead خطوة بخطوة
يعمل الـ typeahead أفضل عندما يُعامل كأداة بحث صغيرة، لا كبسولة قائمة صغيرة. الهدف واضح: جلب بضع مطابقة جيدة بسرعة، السماح للمستخدم بالاختيار، وحفظ التحديد بأمان.
إعداد عملي وسريع
ابدأ بتحديد الحقل أو الحقلين اللذين يتذكرهما الناس بالفعل. للعملاء، عادةً الاسم أو البريد الإلكتروني. للمنتجات، قد يكون SKU أو كود داخلي. هذا الاختيار أهم من التنسيق لأنه يقرر ما إذا كان المستخدمون سيحصلون على نتائج في الضربات الأولى من لوحة المفاتيح.
ثم نفّذ التدفق من البداية للنهاية:
- اختر مفتاح البحث (مثلاً: اسم العميل مع البريد الإلكتروني) وحدد عددًا أدنى من الأحرف (غالبًا 2 إلى 3).
- أنشئ نقطة نهاية API تقبل نص الاستعلام بالإضافة إلى تقسيم الصفحات (مثلاً q وlimit، بالإضافة إلى offset أو مؤشر).
- أعد فقط مجموعة صغيرة (غالبًا أعلى 20)، مرتبة حسب أفضل تطابق، وتضمّن المعرف بالإضافة إلى حقول التسمية التي تريد عرضها.
- في الواجهة، اعرض حالة تحميل، تعامل مع النتائج الفارغة، وادعم التنقل بلوحة المفاتيح.
- احفظ السجل المختار كمعرف، لا كنص عرض، واعتبر التسميات للعرض فقط.
مثال صغير: إذا كتب مسؤول "maria@" في حقل Customer، تستدعي الواجهة نقطة النهاية بـ q=maria@ وتحصل على 20 تطابقًا. يختار المستخدم الصحيح ويحفظ النموذج customer_id=12345. إذا غير هذا العميل لاحقًا اسمه أو بريده، تظل بياناتك المحفوظة صحيحة.
إذا كنت تبني في AppMaster، تنطبق الفكرة نفسها: استخدم نقطة نهاية في الخلفية للبحث (مع تقسيم صفحات)، اربطها بالحقل في الواجهة، وربط القيمة المختارة بمعرف النموذج.
تفصيلان يحافظان على الاستجابة: اجعل الطلبات متباعدة (debounce) حتى لا تستدعي الخادم عند كل ضربة، وخزن استعلامات مؤخّرة داخل الجلسة.
أنماط التصفية على الخادم التي تظل سريعة
بمجرد أن تكبر قائمتك إلى أكثر من بضع مئات من العناصر، يصبح التصفية في المتصفح غير ملائم. الصفحة تنتهي بتحميل بيانات لن تستخدمها، ثم أداء عمل إضافي فقط لعرض شريحة صغيرة.
التصفية على الخادم تعكس التدفق: أرسل استعلامًا صغيرًا (مثل "الاسم يبدأ بـ ali"), استلم فقط الصفحة الأولى من المطابقات، وحافظ على استجابة النموذج سريعة مهما كبر الجدول.
أنماط تُبقي زمن الاستجابة ثابتًا
بعض القواعد البسيطة تحدث فرقًا كبيرًا:
- أعد حجم صفحة محدودًا (مثلاً 20 إلى 50 عنصرًا) وضمّن "رمز التالي" أو رقم الصفحة.
- فضّل تقسيم الصفحات بناءً على مؤشر (cursor) للبيانات المتغيرة حتى تتجنّب الفجوات الغريبة عند إضافة السجلات.
- اطلب من الخادم إرجاع الحقول التي تحتاجها الواجهة فقط (id + label)، لا السجلات كاملة.
- استخدم ترتيبًا ثابتًا (مثلاً بالاسم ثم المعرف) حتى لا تقفز النتائج.
- طبّق صلاحيات المستخدم الحالية داخل الاستعلام، لا بعد ذلك.
التخزين المؤقت: مفيد لكن سهل الخطأ
التخزين المؤقت يمكن أن يسرّع عمليات البحث الشائعة، لكن فقط عندما تكون النتيجة آمنة لإعادة الاستخدام. "أهم الدول" أو "فئات المنتجات الشائعة" مرشحون جيدون. قوائم العملاء غالبًا لا تكون كذلك، لأن النتائج قد تعتمد على الصلاحيات، حالة الحساب، أو تغييرات حديثة.
إذا خزّنت مؤقتًا، اجعلها قصيرة العمر وضمّن دور المستخدم أو المستأجر في مفتاح الكاش. وإلا، قد يرى شخص ما بيانات شخص آخر.
في AppMaster، عادةً ما يعني ذلك بناء نقطة نهاية تقبل نص البحث والمؤشر، ثم فرض قواعد الوصول في منطق الخلفية قبل إرجاع الصفحة التالية من الخيارات.
أنماط بيانات مرجعية تحافظ على سلاسة النماذج
كثير من ألم "القوائم البطيئة" هو في الواقع ألم "البيانات المرجعية الفوضوية". عندما يشير حقل النموذج إلى جدول آخر (عملاء، منتجات، مواقع)، عاملها كمرجع: خزن المعرف، واعتبر التسمية للعرض فقط. هذا يبقي السجلات صغيرة، يتجنب إعادة كتابة التاريخ، ويسهّل البحث والتصفية.
اجعل جداول المرجع مملة ومتسقة. أعطِ كل صف مفتاحًا واضحًا وفريدًا (غالبًا معرف رقمي) واسمًا يتعرف عليه المستخدمون. أضف علمًا نشط/غير نشط بدل الحذف، حتى تظل السجلات القديمة قابلة للحل دون الظهور في الاختيارات الجديدة. هذا يساعد أيضًا الـ typeahead والتصفية على الخادم لأنك تستطيع تصفية active=true افتراضيًا بأمان.
قرّر مبكرًا ما إذا كان يجب عليك حفظ لقطة للتسمية على السجل. قد يخزن سطر الفاتورة customer_id، لكنه قد يخزن أيضًا customer_name_at_purchase للأرشفة والنزاعات. للقيود الإدارية اليومية، غالبًا ما يكون أفضل الانضمام دائمًا وعرض الاسم الحالي، لذلك تظهر التصحيحات للأخطاء في كل مكان. قاعدة بسيطة تعمل جيدًا: احفظ لقطة عندما يجب أن يبقى الماضي قابلاً للقراءة حتى لو تغيّر المرجع.
من أجل السرعة، اختصارات صغيرة يمكنها تقليل البحث دون تحميل مجموعة البيانات الكاملة. "العناصر المستخدمة مؤخرًا" (لكل مستخدم) في الأعلى غالبًا ما تفوق أي تعديل في الواجهة. المفضلات تساعد عندما يختار الناس نفس الأشياء يوميًا. الافتراضات الآمنة (مثل آخر قيمة مستخدمة) يمكنها إزالة تفاعلات كاملة. وإخفاء العناصر غير النشطة ما لم يطلب المستخدم ذلك يبقي القائمة نظيفة.
مثال: عند اختيار مستودع على أمر شراء. خزن warehouse_id على الطلب. اعرض اسم المستودع، لكن لا تضمّنه ما لم تكن بحاجة إلى أثر تدقيقي. في AppMaster، يتوافق هذا بسهولة: نمذج المرجع في Data Designer، واستخدم منطق الأعمال لتسجيل "الاختيارات الأخيرة" دون تحميل آلاف الخيارات في الواجهة.
سيناريوهات نموذجية وأدوات واجهة مستخدم أفضل
تظهر القوائم المنسدلة الضخمة لأن حقل النموذج يبدو "بسيطًا": اختر قيمة واحدة من قائمة. لكن حقول الإدارة الحقيقية غالبًا ما تحتاج أدوات مختلفة لتظل سريعة وسهلة.
الحقول التابعة حالة كلاسيكية. إذا كانت المدينة تعتمد على البلد، حمّل الحقل الأول فقط عند تحميل الصفحة. عندما يختار المستخدم بلدًا، اجلب المدن لذلك البلد. إذا كانت قائمة المدن لا تزال كبيرة، اجعل حقل المدينة نوعًا من typeahead الذي يرشّح ضمن البلد المختار.
حقول الاختيار المتعدد (الوسوم، الأدوار، الفئات) تنهار بسرعة مع القوائم الكبيرة. اختيار متعدد يعتمد على البحث يُحمِّل النتائج أثناء كتابة المستخدم ويعرض العناصر المختارة كرُقائق (chips) يتجنب تحميل آلاف الخيارات لمجرد اختيار ثلاثة.
حاجة شائعة أخرى هي "إنشاء جديد" من الحقل عندما يكون الخيار مفقودًا. ضع إجراء "إضافة جديد..." بجانب الحقل أو داخل المُختار. أنشئ السجل الجديد، ثم اختره تلقائيًا. حقق على الخادم (الحقول المطلوبة، التفرد حيث يهم) وتعامل مع التعارضات بوضوح.
لقوائم مرجعية طويلة (عملاء، منتجات، موردون)، استخدم حوار بحث أو typeahead مع تصفية على الخادم. اعرض سياقًا في النتائج (مثلاً: اسم العميل مع البريد الإلكتروني) حتى يختار الناس بشكل صحيح.
الشبكة السيئة واللحظات دون اتصال تجعل القوائم الكبيرة أسوأ. بعض الاختيارات تساعد التطبيقات الداخلية على البقاء قابلة للاستخدام: خزّن الاختيارات الأخيرة الشائعة (مثل آخر 10 عملاء) حتى تظهر الاختيارات الشائعة فوريًا، اعرض حالة تحميل واضحة، ادعم إعادة المحاولة دون مسح إدخال المستخدم، ودع المستخدمين يواصلون ملء الحقول الأخرى أثناء تحميل الاستعلامات.
إذا بنيت النماذج في AppMaster، تتطابق هذه الأنماط جيدًا مع نموذج بيانات نظيف (جداول مرجعية) بالإضافة إلى نقاط نهاية خادم لبحث مُفلتر، بحيث تظل الواجهة سريعة مع نمو البيانات.
أخطاء شائعة تجعل الوضع أسوأ
معظم النماذج البطيئة ليست بطيئة بسبب جدول ضخم واحد. تصبح بطيئة لأن الواجهة تكرر الاختيار المكلف مرارًا.
خطأ كلاسيكي هو تحميل القائمة الكاملة "مرة واحدة" عند تحميل الصفحة. يبدو الأمر جيدًا مع 2000 عنصر. بعد عام يصبح 200,000، وتُفتح كل صفحة مع انتظار طويل، واستهلاك ذاكرة زائد، وحمولة كبيرة.
قد يفشل البحث حتى عندما يكون سريعًا. إذا كان الحقل يبحث بالاسم الظاهر فقط، فقد يعلق المستخدمون. الناس يبحثون بما لديهم: بريد العميل، كود داخلي، رقم هاتف، أو آخر 4 أرقام من حساب.
بضع قضايا تحول تحكم مقبول إلى مؤلم:
- لا توجد تقليل (debounce)، فتُرسل الواجهة طلبًا عند كل ضربة مفتاح.
- حمولات ضخمة (سجلات كاملة) بدلًا من قائمة صغيرة من المطابقات.
- العناصر غير النشطة أو المحذوفة لا تُعالج، فتظهر فراغات لاحقًا في النماذج المحفوظة.
- النموذج يخزن نص التسمية بدلًا من المعرف، مما يخلق تكرارات وتقارير فوضوية.
- النتائج لا تعرض سياقًا كافيًا (مثلاً، اثنان "John Smith" بدون مميز).
سيناريو حقيقي: وكيل يختار عميلًا. يوجد "Acme" مرتين، أحدهما غير نشط، والنموذج خزن التسمية. الآن الفاتورة تشير إلى السجل الخاطئ ولا أحد يستطيع إصلاحه بثقة.
في AppMaster، الافتراض الآمن هو الاحتفاظ بالمراجع كمعرفات في نموذج البيانات وعرض التسميات فقط في الواجهة، بينما نقطة البحث تعيد قوائم مطابقة صغيرة ومرشّحة.
قائمة تحقق سريعة قبل إطلاق النموذج
قبل الإطلاق، عامل كل حقل "اختر من قائمة" كمخاطرة أداء وتجربة مستخدم. هذه الحقول غالبًا تبدو جيدة مع بيانات الاختبار، ثم تنهار عندما تظهر السجلات الحقيقية.
- إذا كانت القائمة قد تتجاوز حوالي 100 عنصر، انتقل إلى typeahead أو أداة اختيار قابلة للبحث.
- اجعل استجابات البحث صغيرة. اهدف لإرجاع نحو 20 إلى 50 نتيجة لكل استعلام، وقدم تلميحًا واضحًا عندما يجب على المستخدم الاستمرار في الكتابة.
- احفظ القيمة الثابتة، لا التسمية. خزن معرف السجل وحقّق صحته على الخادم، بما في ذلك فحوصات الصلاحية، قبل قبول النموذج.
- تعامل مع الحالات عن قصد: مؤشر تحميل أثناء البحث، حالة فارغة مفيدة عندما لا يوجد تطابق، وأخطاء واضحة عند فشل الطلب.
- اجعلها سريعة دون استخدام الفأرة. ادعم التنقل عبر لوحة المفاتيح ودع المستخدمين يلصقون اسمًا أو بريدًا أو كودًا في مربع البحث.
إذا كنت تبني في أداة بلا كود مثل AppMaster، غالبًا ما يكون هذا تغييرًا صغيرًا: واجهة إدخال واحدة، نقطة نهاية بحث واحدة، ومنطق تحقق على الخادم. الفرق في العمل اليومي الإداري كبير، خاصة في النماذج عالية الاستخدام.
مثال واقعي: اختيار عميل في لوحة إدارة
فريق الدعم يعمل في واجهة إدارة يخصّص كل تذكرة واردة إلى العميل الصحيح. يبدو بسيطًا حتى تصل قائمة العملاء إلى 8,000 سجل.
النسخة "قبل" تستخدم قائمة منسدلة عملاقة. تستغرق لحظة للفتح، التمرير يتلعثم، والمتصفح يضطر للاحتفاظ بآلاف الخيارات في الذاكرة. والأسوأ من ذلك أن الناس يختارون "Acme" الخاطئ بسبب التكرارات والأسماء القديمة والفروقات الطفيفة مثل "ACME Inc" مقابل "Acme, Inc.". النتيجة خسارة وقت صغيرة لكن مستمرة، بالإضافة إلى تقارير فوضوية لاحقًا.
النسخة "بعد" تستبدل القائمة بحقل typeahead. يكتب الوكيل ثلاث حروف، تعرض الواجهة أفضل المطابقات سريعًا، ويختار وينتقل. يمكن للحقل عرض سياق إضافي (نطاق البريد الإلكتروني، معرف الحساب، المدينة) حتى يصبح العميل الصحيح واضحًا.
للحفاظ على السرعة، يتم البحث على الخادم، لا في المتصفح. تطلب الواجهة فقط أول 10 إلى 20 تطابقًا، مرتبة حسب الصلة (غالبًا مزيج من التطابق التمهيدي و"الأكثر استخدامًا مؤخرًا") ومفلترة بالحالة (مثلاً: العملاء النشطون فقط). هذا النمط يمنع القوائم الطويلة من التحول إلى مصدر إزعاج يومي.
خطوة صغيرة في نقاء البيانات تجعل التدفق الجديد أكثر أمانًا:
- ضع قاعدة تسمية (مثلاً: الاسم القانوني + المدينة أو النطاق).
- امنع التكرارات في الحقول الأساسية (مجال البريد، رقم الضريبة، أو معرف خارجي).
- حافظ على حقل "عرض الاسم" متسقًا عبر المنتج.
- اجعل السجلات المدموجة غير نشطة، لكن احتفظ بالتاريخ.
في أداة مثل AppMaster، عادةً ما يعني هذا حقل مرجعي قابل للبحث مدعومًا بنقطة نهاية API تُعيد المطابقات أثناء كتابة المستخدم، بدلًا من تحميل كل العملاء في النموذج مقدمًا.
الخطوات التالية: حسّن حقلًا واحدًا وقيّس النمط
اختر قائمة منسدلة واحدة يشتكي منها الجميع. مرشح جيد هو الحقل الذي يظهر في شاشات كثيرة (Customer، Product، Assignee) وقد نما إلى ما بعد بضع مئات من العناصر. استبدال هذا الحقل فقط يمنحك إثباتًا سريعًا دون إعادة كتابة كل النماذج.
ابدأ بتحديد ما يشير إليه الحقل فعليًا: جدول مرجعي (عملاء، مستخدمون، SKUs) بمعرف ثابت، بالإضافة إلى مجموعة صغيرة من حقول العرض (الاسم، البريد، الكود). ثم عرّف نقطة نهاية بحث تعيد فقط ما تحتاجه الواجهة بسرعة، في صفحات صغيرة.
خطة نشر تعمل مع الفرق الحقيقية:
- استبدل القائمة المنسدلة بـ typeahead لذلك الحقل.
- أضف بحثًا على الخادم يدعم النص الجزئي والتقسيم.
- أعد معرفًا + تسمية (وحقل تلميح ثانٍ مثل البريد).
- احتفظ بالقيمة المختارة كمعرف، لا نص منسوخ.
- أعِد استخدام نفس النمط أينما تم اختيار هذا الكيان.
قِس التغيير بعدة أرقام أساسية. تتبع زمن فتح الحقل (يجب أن يبدو فوريًا)، زمن الاختيار (يجب أن ينخفض)، ومعدل الأخطاء (الاختيارات الخاطئة، إعادة التحرير، أو تفوق المستخدمين). حتى فحص قبل/بعد خفيف مع 5 إلى 10 مستخدمين حقيقيين يمكن أن يظهر ما إذا كنت أصلحت الألم.
إذا تبني أدوات إدارية بـ AppMaster، يمكنك نمذجة البيانات المرجعية في Data Designer وإضافة منطق بحث على الخادم في Business Process Editor، بحيث تطلب الواجهة شريحة صغيرة من النتائج بدلًا من تحميل كل شيء. غالبًا ما يتبنى الفرق هذا النمط عبر التطبيقات الداخلية المبنية على appmaster.io لأنّه يتدرج بسلاسة مع نمو الجداول.
أخيرًا، اكتب معيارًا يمكن للفريق إعادة استخدامه: الحد الأدنى للحروف قبل البحث، حجم الصفحة الافتراضي، كيفية تنسيق التسميات، وماذا يحدث عندما لا توجد نتائج. الاتساق هو ما يحفظ كل نموذج جديد سريعًا.
الأسئلة الشائعة
القائمة المنسدلة عادةً مناسبة عندما تكون الخيارات قليلة، ثابتة، وسهلة المسح بصريًا. إذا لم يستطع الأشخاص العثور على الخيار الصحيح بسهولة دون الكتابة، أو إذا كانت القائمة مرشحة للنمو، فانتقل إلى أداة اختيار تعتمد على البحث قبل أن تتحول إلى مصدر إزعاج يومي.
فرق الفرق عادةً تبدأ بالشعور بالإعاقة في المئات القليلة لأن المسح يصبح أبطأ وتزداد الأخطاء بالنقر. عند الوصول إلى الآلاف، تصبح اهتزازات الأداء والاختيارات الخاطئة شائعة، وعند عشرات الآلاف تتوقف القائمة المنسدلة عن كونها تحكمًا معقولًا.
ابدأ بحد أدنى 2–3 أحرف قبل إجراء البحث، وأعد مجموعة نتائج صغيرة مثل 10–20 نتيجة. اجعل الاختيار سريعًا بدعم لوحة المفاتيح، وعرِض سياقًا كافيًا في كل نتيجة (مثلاً: اسم + بريد إلكتروني أو كود) حتى تُمَيِّز السجلات المكررة بسهولة.
استخدم التقليل (debounce) بحيث لا تُرسل طلبًا عند كل ضغطة مفتاح، واجعل الخادم يتولى التصفية. أبقِ الاستجابات صغيرة بإرجاع الحقول اللازمة فقط لعرض قائمة الاقتراحات، بالإضافة إلى معرف ثابت للحفظ في النموذج.
قم بالتصفية والتقسيم على الخادم، لا في المتصفح. يجب أن ترسل الواجهة سؤالًا قصيرًا وتتلقى صفحة واحدة من المطابقات فقط، حتى يظل الأداء ثابتًا مع نمو الجدول من آلاف إلى ملايين السجلات.
خزن معرف السجل المُختار، لا التسمية المعروضة، لأن الأسماء والتسميات تتغير. حفظ المعرفات يمنع المراجع المكسورة، ويقلل التكرارات، ويجعل التقارير والربط بين الجداول موثوقًا حتى لو تغيّرت النصوص.
اعرض تفاصيل مميزة في النتائج مثل البريد الإلكتروني، المدينة، الكود الداخلي، أو رقم حساب حتى يصبح الخيار الصحيح واضحًا. قلل التكرارات على مستوى البيانات حيث يمكن، وأخفِ السجلات غير النشطة افتراضيًا حتى لا يختارها المستخدمون عن طريق الخطأ.
لا تحمل القائمتين معًا مُسبقًا. حمِّل الحقل الأول، ثم احصل على المدن بناءً على اختيار البلد، وإذا كانت قائمة المدن كبيرة فاجعل حقل المدينة نوعًا من typeahead مخصّصًا لذلك النطاق بحيث يبقى الاستعلام ضيقًا وسريعًا.
خزن "الأكثر استخدامًا مؤخرًا" لكل مستخدم حتى تظهر الاختيارات الشائعة فورًا، واحتفظ ببقية البيانات خلف بحث يمكن إعادة المحاولة عليه بأمان. اجعل حالات التحميل والأخطاء واضحة دون منع بقية النموذج من العمل، حتى يتمكن المستخدمون من ملء حقول أخرى أثناء انتظار نتائج البحث.
أنشئ نقطة نهاية خلفية تقبل نص بحث وتُعيد قائمة صغيرة مُقسَّمة من المطابقات مع معرفات وحقول عرض. في الواجهة اربط حقل الـ typeahead بتلك النقطة، اعرض الاقتراحات، واحفظ المعرف المختار إلى النموذج؛ في AppMaster عادةً هذا يتوافق مع نقطة نهاية backend وربط واجهة المستخدم مع فرض قواعد الوصول داخل منطق الخادم.


