هندسة نماذج Vue 3 لتطبيقات الأعمال: أنماط قابلة لإعادة الاستخدام
هندسة نماذج Vue 3 لتطبيقات الأعمال: مكونات حقول قابلة لإعادة الاستخدام، قواعد تحقق واضحة، وطرق عملية لعرض أخطاء الخادم بجانب كل إدخال.

لماذا ينهار كود النماذج في تطبيقات الأعمال الحقيقية
نادرًا ما يبقى النموذج في تطبيق عمل صغيرًا. يبدأ كـ "بضع حقول فقط" ثم يكبر ليشمل عشرات الحقول، أقسامًا شرطية، أذونات، وقواعد يجب أن تبقى متزامنة مع منطق الخادم. بعد بعض تغييرات المنتج، يظل النموذج يعمل، لكن الكود يبدأ أن يبدو هشًا.
هندسة نماذج Vue 3 مهمة لأن النماذج هي المكان الذي تتكدس فيه "الإصلاحات السريعة": واطٍ آخر من watcher، حالة خاصة واحدة إضافية، مكون منسوخ آخر. يعمل اليوم، لكن يصبح من الأصعب الوثوق به ومن الأصعب تغييره.
علامات التحذير مألوفة: سلوك الإدخالات مكرر عبر الصفحات (التسميات، التنسيق، علامات الإلزام، التلميحات)، وضع الأخطاء غير متسق، قواعد التحقق مبعثرة عبر المكونات، وأخطاء الخادم تُختزل إلى إشعار عام لا يخبر المستخدم بما يجب إصلاحه.
هذه التباينات ليست مجرد قضايا أسلوبية في الكود. تتحول إلى مشاكل تجربة مستخدم: يعيد الناس إرسال النماذج، تزداد تذاكر الدعم، وتتجنّب الفرق لمس النماذج لأن شيئًا قد ينكسر في حالة طرفية مخفية.
إعداد جيد يجعل النماذج مملة بأفضل معنى. مع هيكل متوقع، يمكنك إضافة حقول، تغيير قواعد، ومعالجة استجابات الخادم دون إعادة توصيل كل شيء.
تريد نظام نماذج يمنحك إعادة استخدام (حقل واحد يتصرف نفسه في كل مكان)، وضوح (القواعد ومعالجة الأخطاء سهلة المراجعة)، سلوك متوقع (touched، dirty، reset، submit)، وردود أفضل (أخطاء الخادم تظهر على المدخلات الدقيقة التي تحتاج انتباهاً). تركز الأنماط أدناه على مكونات الحقول القابلة لإعادة الاستخدام، تحقق واضح القراءة، وتعيين أخطاء الخادم إلى المدخلات المحددة.
نموذج ذهني بسيط لبنية النموذج
النموذج الذي يثبت بمرور الوقت هو نظام صغير بأجزاء واضحة، وليس كومة مدخلات.
فكّر في أربع طبقات تتحدث مع بعضها في اتجاه واحد: واجهة المستخدم تجمع الإدخال، حالة النموذج تخزنه، التحقق يشرح ما هو خطأ، وطبقة API تحمل وتحفظ.
الأربع طبقات (وما يملكه كل منها)
- مكون واجهة الحقل: يعرض المدخل، التسمية، التلميح، ونص الخطأ. يصدر تغيّرات القيمة.
- حالة النموذج: تخزن القيم والأخطاء (بالإضافة إلى أعلام touched وdirty).
- قواعد التحقق: دوال نقية تقرأ القيم وتعيد رسائل الخطأ.
- استدعاءات API: تحميل البيانات الأولية، إرسال التغييرات، وترجمة استجابات الخادم إلى أخطاء حقل.
هذا الفصل يبقي التغييرات محصورة. عندما يصل متطلب جديد، تحدّث طبقة واحدة دون كسر الأخريات.
ماذا ينتمي للحقل مقابل النموذج الأب
يجب أن يكون مكون الحقل القابل لإعادة الاستخدام بسيطًا. لا ينبغي أن يعرف عن API الخاص بك، أو نموذج البيانات، أو قواعد التحقق. يجب أن يعرض قيمة ويعرض خطأ فقط.
النموذج الأب ينسق كل شيء الآخر: أي الحقول موجودة، أين تعيش القيم، متى نتحقق، وكيف نُرسل.
قاعدة بسيطة تساعد: إذا اعتمد المنطق على حقول أخرى (مثلاً، "الولاية" مطلوبة فقط عندما تكون "البلد" هي الولايات المتحدة)، فاحتفظ به في النموذج الأب أو طبقة التحقق، وليس داخل مكون الحقل.
عند إضافة حقل جديد بسهولة قليلة الجهد، عادةً ما تلمس فقط الافتراضات أو المخطط، والعنصر في الـ markup حيث يُوضع الحقل، وقواعد التحقق الخاصة بالحقل. إذا كان إضافة إدخال واحد يجبرك على تغييرات عبر مكونات غير مرتبطة، فحدودك غامضة.
مكونات الحقول القابلة لإعادة الاستخدام: ما يجب توحيده
عندما تكبر النماذج، أسرع فائدة هي التوقف عن بناء كل إدخال كما لو كان حالة فريدة. يجب أن تشعر مكونات الحقول بأنها متوقعة. هذا ما يجعلها سريعة الاستخدام وسهلة المراجعة.
مجموعة عملية من اللبنات:
- BaseField: غلاف للتسمية، التلميح، نص الخطأ، المسافات، وسمات الوصول.
- مكونات الإدخال: TextInput، SelectInput، DateInput، Checkbox، وهكذا. كل واحد يركز على عنصر التحكم.
- FormSection: يجمع الحقول المرتبطة بعنوان، نص مساعدة قصير، وتباعد متسق.
بالنسبة للـ props، احتفظ بمجموعة صغيرة وطبقها في كل مكان. تغيير اسم prop عبر 40 نموذجًا مؤلم.
عادةً ما تؤتي هذه النتائج ثمرة فورية:
modelValueوupdate:modelValueلـv-modellabelrequireddisablederror(رسالة واحدة، أو مصفوفة إذا فضّلت)hint
الـ slots هي حيث تسمح بالمرونة دون كسر التناسق. حافظ على تخطيط BaseField ثابتًا، لكن اسمح بتباينات صغيرة مثل إجراء على الجانب الأيمن ("إرسال رمز") أو أيقونة بادئة. إذا ظهرت تباينة مرتين، اجعلها slot بدلًا من تشعب المكون.
وَحّد ترتيب العرض (التسمية، عنصر التحكم، التلميح، الخطأ). المستخدمون يمسحون العين أسرع، والاختبارات تصبح أبسط، وتعيين أخطاء الخادم يصبح واضحًا لأن لكل حقل مكانًا واضحًا لعرض الرسائل.
حالة النموذج: القيم، touched، dirty، وإعادة التعيين
معظم أخطاء النماذج في تطبيقات الأعمال ليست حول المدخلات. تأتي من حالة منتشرة: قيم في مكان، أخطاء في مكان آخر، وزر إعادة تعيين يعمل جزئيًا. تبدأ هندسة نماذج Vue 3 النظيفة بشكل حالة واحد متسق.
أولًا، اختر مخطط تسمية لمفاتيح الحقول والتزم به. أبسط قاعدة: مفتاح الحقل يساوي مفتاح حمولة الـ API. إذا كان خادمك يتوقع first_name، يجب أن يكون مفتاح النموذج first_name أيضًا. هذا الاختيار الصغير يجعل التحقق، الحفظ، وتعيين أخطاء الخادم أسهل بكثير.
احفظ حالة النموذج في مكان واحد (composable، مخزن Pinia، أو مكوّن أب)، ودع كل حقل يقرأ ويكتب عبر تلك الحالة. بنية مسطحة تعمل لمعظم الشاشات. لا تذهب إلى التعشيش إلا عندما تكون الـ API متعششة حقًا.
const state = reactive({
values: { first_name: '', last_name: '', email: '' },
touched: { first_name: false, last_name: false, email: false },
dirty: { first_name: false, last_name: false, email: false },
errors: { first_name: '', last_name: '', email: '' },
defaults: { first_name: '', last_name: '', email: '' }
})
طريقة عملية للتفكير في الأعلام:
touched: هل تفاعل المستخدم مع هذا الحقل؟dirty: هل القيمة مختلفة عن القيمة الافتراضية (أو آخر قيمة محفوظة)؟errors: ما الرسالة التي يجب أن يراها المستخدم الآن؟defaults: ما الذي نُعيد إليه عند إعادة التعيين؟
يجب أن يكون سلوك إعادة التعيين متوقعًا. عند تحميل سجل موجود، اضبط كلًا من values وdefaults من نفس المصدر. عندها reset() يمكنه نسخ defaults مرة أخرى إلى values، ومسح touched وdirty وerrors.
مثال: نموذج ملف عميل يحمّل email من الخادم. إذا حرّره المستخدم، يصبح dirty.email صحيحًا. إذا نقروا إعادة تعيين، يعود البريد الإلكتروني إلى القيمة المحمّلة (ليس سلسلة فارغة)، وتبدو الشاشة نظيفة مرة أخرى.
قواعد التحقق التي تبقى مقروءة
القابلية لقراءة التحقق أقل عن المكتبة وأكثر عن كيفية التعبير عن القواعد. إذا استطعت إلقاء نظرة على حقل وفهم قواعده في بضع ثوانٍ، يبقى كود النموذج قابلاً للصيانة.
اختر نمط قواعد يمكنك الالتزام به
تستقر معظم الفرق في أحد هذه النهج:
- قواعد لكل حقل: القواعد تعيش قرب استخدام الحقل. سهل الفحص، ممتاز للنماذج الصغيرة إلى المتوسطة.
- قواعد على شكل مخطط: القواعد في كائن واحد أو ملف. ممتاز متى ما أعادت الشاشات استخدام نفس النموذج.
- هجينة: قواعد بسيطة بجوار الحقول، والقواعد المشتركة أو المعقّدة في مخطط مركزي.
أياً كانت الطريقة، اجعل أسماء الرسائل والقواعد متوقعة. بعض القواعد الشائعة (required، length، format، range) أفضل من قائمة طويلة من المساعدين الخاصين.
اكتب القواعد كجملة بالإنجليزية البسيطة
قواعد جيدة تُقرأ كجملة: "البريد الإلكتروني مطلوب ويجب أن يشبه بريدًا إلكترونيًا." تجنّب السطور الذكية التي تختبئ فيها النية.
لأغلب نماذج الأعمال، إعادة رسالة واحدة لكل حقل في المرة (الفشل الأول) تبقي الواجهة هادئة وتساعد المستخدمين على إصلاح المشاكل أسرع.
قواعد شائعة صديقة للمستخدم:
- مطلوب فقط عندما يجب فعلًا ملء الحقل.
- الطول بأرقام حقيقية (مثال: من 2 إلى 50 حرفًا).
- التنسيق للبريد، الهاتف، الرمز البريدي، دون regex صارم يرفض مدخلات حقيقية.
- النطاق مثل "التاريخ ليس في المستقبل" أو "الكمية بين 1 و999."
اجعل الفحوصات غير المتزامنة واضحة
التحقق غير المتزامن (مثل "اسم المستخدم مستخدم") يصبح مربكًا إذا شُغّل بصمت.
شغّل الفحوصات عند الخروج أو بعد توقف قصير، عرض حالة "جارٍ التحقق..." واضحة، وألغِ أو تجاهل الطلبات القديمة عندما يستمر المستخدم بالكتابة.
قرّر متى يعمل التحقق
التوقيت مهم مثل القواعد. إعداد ودود للمستخدم يكون:
- عند التغيير للحقول التي تستفيد من ردود فعل حية (مثل قوة كلمة المرور)، لكن اجعلها لطيفة.
- عند الخروج لمعظم الحقول، حتى يتمكن المستخدم من الكتابة دون أخطاء مستمرة.
- عند الإرسال للنموذج كشبكة أمان نهائية.
تعيين أخطاء الخادم إلى المدخل الصحيح
التحققات على جهة العميل هي نصف القصة فقط. في تطبيقات الأعمال، يرفض الخادم الحفظ لقواعد لا يعرفها المتصفح: التكرارات، فحوصات الأذونات، البيانات البالية، تغيّرات الحالة، والمزيد. تجربة النموذج الجيدة تعتمد على تحويل تلك الاستجابة إلى رسائل واضحة بجانب المدخلات الصحيحة.
طبع الأخطاء إلى شكل داخلي واحد
نادراً ما تتفق الخوادم على صيغة الأخطاء. بعضها يعيد كائنًا واحدًا، البعض يعيد قوائم، وبعضها يعيد خرائط متعششة مفاتيحها أسماء الحقول. حوّل أي شيء تتلقاه إلى شكل داخلي واحد يمكن لنموذجك عرضه.
// ما يستهلكه كود نموذجك
{
fieldErrors: { "email": ["Already taken"], "address.street": ["Required"] },
formErrors: ["You do not have permission to edit this customer"]
}
احفظ بعض القواعد متسقة:
- خزن أخطاء الحقول كمصفوفات (حتى لو كانت رسالة واحدة).
- حول أنماط المسارات المختلفة إلى نمط واحد (مسارات بنقاط تعمل جيدًا:
address.street). - احتفظ بالأخطاء غير المرتبطة بالحقول منفصلة تحت
formErrors. - احتفظ بالحمولة الخام للخادم للتسجيل، لكن لا تعرضها.
طابق مسارات الخادم بمفاتيح الحقول لديك
الجزء المعقّد هو مواءمة فكرة الخادم عن "مسار" مع مفاتيح الحقول في النموذج. قرّر مفتاح كل مكون حقل (مثلاً، email، profile.phone، contacts.0.type) والتزم به.
ثم اكتب محولًا صغيرًا يتعامل مع الحالات الشائعة:
address.street(بصيغة النقاط)address[0].street(أقواس للمصفوفات)/address/street(أسلوب JSON Pointer)
بعد التطبيع، يجب أن يكون <Field name="address.street" /> قادرًا على قراءة fieldErrors["address.street"] بدون حالات خاصة.
ادعم الأسماء المستعارة عند الحاجة. إذا أعاد الخادم customer_email لكن الواجهة تستخدم email، احتفظ بتعيين مثل { customer_email: "email" } أثناء التطبيع.
أخطاء الحقول، الأخطاء على مستوى النموذج، والتركيز
ليست كل الأخطاء تنتمي إلى مدخل واحد. إذا قال الخادم "تم تجاوز حد الخطة" أو "الدفع مطلوب"، اعرضها فوق النموذج كرسالة على مستوى النموذج.
لأخطاء الحقول المحددة، اعرض الرسالة بجانب المدخل ووجّه المستخدم إلى المشكلة الأولى:
- بعد ضبط أخطاء الخادم، اعثر على المفتاح الأول في
fieldErrorsالموجود في نموذجك المعروض. - قم بتمريره إلى العرض وركّزه (باستخدام مرجع لكل حقل و
nextTick). - امسح أخطاء الخادم لحقل عندما يقوم المستخدم بتعديله مجددًا.
خطوة بخطوة: جمع البنية معًا
النماذج تبقى هادئة عندما تقرر مبكرًا ما ينتمي إلى حالة النموذج، الواجهة، التحقق، وAPI، ثم توصلها بعدد قليل من الدوال الصغيرة.
تسلسل يعمل لمعظم تطبيقات الأعمال:
- ابدأ بنموذج واحد ومفاتيح حقول ثابتة. تصبح هذه المفاتيح العقدة المشتركة بين المكونات، المدققين، وأخطاء الخادم.
- أنشئ غلاف
BaseFieldواحدًا للتسمية، نص المساعدة، علامة الإلزام، وعرض الأخطاء. اجعل مكونات الإدخال صغيرة ومتسقة. - أضف طبقة تحقق يمكنها التشغيل per-field ويمكنها التحقق من كل شيء عند الإرسال.
- أرسل إلى API. إذا فشل، ترجم أخطاء الخادم إلى
{ [fieldKey]: message }حتى يظهر كل خطأ عند المدخل الصحيح. - احتفظ بمعالجة النجاح منفصلة (reset، إشعار، تنقل) حتى لا تتسرّب إلى المكونات والمدققين.
نقطة بداية بسيطة للحالة:
const values = reactive({ email: '', name: '', phone: '' })
const touched = reactive({ email: false, name: false, phone: false })
const errors = reactive({}) // { email: '...', name: '...' }
يحصل BaseField على label وerror وربما touched ويعرض الرسالة في مكان واحد. يهتم كل مكون إدخال فقط بالربط وإصدار التحديثات.
للتحقق، احتفظ بالقواعد قرب الموديل باستخدام نفس المفاتيح:
const rules = {
email: v => (!v ? 'Email is required' : /@/.test(v) ? '' : 'Enter a valid email'),
name: v => (v.length < 2 ? 'Name is too short' : ''),
}
function validateAll() {
Object.keys(rules).forEach(k => {
const msg = rules[k](values[k])
if (msg) errors[k] = msg
else delete errors[k]
touched[k] = true
})
return Object.keys(errors).length === 0
}
عندما يرد الخادم بأخطاء، عينها باستخدام نفس المفاتيح. إذا أعادت الـ API { "field": "email", "message": "Already taken" }، اضبط errors.email = 'Already taken' وضعه كممسوح (touched). إذا كان الخطأ عامًا (مثل "permission denied")، اعرضه فوق النموذج.
سيناريو مثال: تعديل ملف عميل
تخيل شاشة إدارة داخلية حيث يقوم موظف دعم بتعديل ملف عميل. النموذج به أربعة حقول: name، email، phone، وrole (Customer, Manager, Admin). النموذج صغير لكنه يظهر القضايا الشائعة.
يجب أن تكون قواعد العميل واضحة:
- Name: مطلوب، طول أدنى.
- Email: مطلوب، تنسيق بريد إلكتروني صالح.
- Phone: اختياري، ولكن إذا مُلئ يجب أن يطابق الصيغة المقبولة.
- Role: مطلوب، وأحيانًا شرطي (فقط المستخدمين ذوي الأذونات المناسبة يمكنهم تعيين Admin).
عقد مكونات متسقة تساعد: كل حقل يستقبل القيمة الحالية، نص الخطأ الحالي (إن وُجد)، وبعض البوليانات مثل touched وdisabled. لا يُعاد اختراع التسميات، علامات الإلزام، المسافات، وتنسيق الأخطاء في كل شاشة.
الآن تدفق تجربة المستخدم. يُحرّر الوكيل البريد الإلكتروني، يضغط تبويب، ويرى رسالة مضمّنة تحت Email إن كان التنسيق خاطئًا. يُصلحها، يضغط حفظ، ويجيب الخادم:
- email already exists: اعرضها تحت Email وركّز ذلك الحقل.
- phone invalid: اعرضها تحت Phone.
- permission denied: اعرض رسالة مستوى نموذج في الأعلى.
إذا احتفظت بالأخطاء مفهرسة باسم الحقل (email، phone، role) يصبح التعيين بسيطًا. تهبط أخطاء الحقول بجانب المدخلات، وأخطاء مستوى النموذج في منطقة مخصصة.
أخطاء شائعة وكيفية تجنّبها
اجعل المنطق في مكان واحد
نسخ قواعد التحقق عبر كل شاشة يبدو سريعًا حتى تتغير السياسات (قواعد كلمات المرور، معرفات الضرائب المطلوبة، نطاقات النطاق المسموح بها). احتفظ بالقواعد مركزية (مخطط، ملف قواعد، دالة مشتركة)، ودع النماذج تستهلك نفس مجموعة القواعد.
وتجنّب أيضًا أن تقوم المكونات الدنيا بالكثير. إذا كان <TextField> يعرف كيف يستدعي API، يعيد المحاولة عند الفشل، ويحلل حمولة أخطاء الخادم، فإنه يتوقف عن كونه قابلًا لإعادة الاستخدام. يجب أن تعرض مكونات الحقل، تصدر تغيّرات القيمة، وتعرض الأخطاء. ضع استدعاءات الـ API ومنطق التعيين في حاوية النموذج أو composable.
أعراض خلط الاهتمامات:
- رسالة التحقق نفسها مكتوبة في أماكن متعددة.
- مكون الحقل يستورد عميل API.
- تغيير نقطة نهاية يكسر عدة نماذج غير مرتبطة.
- اختبارات تتطلب تركيب نصف التطبيق فقط لاختبار إدخال واحد.
كمائن تجربة المستخدم وإمكانية الوصول
لا تكفي لافتة خطأ واحدة مثل "حدث خطأ ما". يحتاج الناس لمعرف ما الحقل الخاطئ وما الذي يجب فعله بعده. استخدم اللافتات للأخطاء العامة (انقطاع الشبكة، رفض الأذونات)، وقُم بتعيين أخطاء الخادم إلى الحقول المحددة حتى يصلحها المستخدم بسرعة.
مشاكل التحميل والإرسال المزدوج تخلق حالات مربكة. عند الإرسال، عطل زر الإرسال، عطّل الحقول التي لا يجب تغييرها أثناء الحفظ، واعرض حالة انشغال واضحة. تأكد من أن إعادة التعيين والإلغاء يعيدان النموذج نظيفًا.
أساسيات إمكانية الوصول سهلة التجاوز مع مكونات مخصصة. بعض الخيارات تمنع ألمًا حقيقيًا:
- كل إدخال له تسمية مرئية (ليس فقط نص عنصر نائب).
- الأخطاء مرتبطة بالحقول بسمات aria صحيحة.
- التركيز ينتقل إلى أول حقل غير صالح بعد الإرسال.
- الحقول المعطّلة غير تفاعلية فعليًا ويتم إعلانها بشكل صحيح.
- التنقل عبر لوحة المفاتيح يعمل من البداية للنهاية.
قائمة تحقق سريعة وخطوات قادمة
قبل إطلاق نموذج جديد، مرّ بقائمة التحقق السريعة. تلتقط الفجوات الصغيرة التي تتحول لاحقًا إلى تذاكر دعم.
- هل لكل حقل مفتاح ثابت يطابق الحمولة والخادم (بما في ذلك المسارات المتعششة مثل
billing.address.zip)? - هل يمكنك عرض أي حقل باستخدام واجهة مكون واحد متسقة (قيمة داخلة، أحداث خارجة، خطأ وتلميح داخلة)؟
- عند الإرسال، هل تتحقق مرة واحدة، تحظر الإرسال المزدوج، وتركّز على أول حقل غير صالح حتى يعرف المستخدم من أين يبدأ؟
- هل يمكنك عرض الأخطاء في المكان الصحيح: لكل حقل (بجانب المدخل) وعلى مستوى النموذج (رسالة عامة عند الحاجة)؟
- بعد النجاح، هل تعيد الحالة بشكل صحيح (values، touched، dirty) حتى يبدأ التعديل التالي نظيفًا؟
إذا كان جواب أحدها "لا" فاصلحه أولًا. ألم النماذج الأكثر شيوعًا هو عدم التطابق: أسماء الحقول تنحرف عن الـ API، أو تعود أخطاء الخادم بشكل لا يستطيع واجهتك وضعها.
إذا كنت تبني أدوات داخلية وتريد التحرك أسرع، يتبع AppMaster (appmaster.io) نفس الأساسيات: حافظ على واجهة حقول متسقة، مركز القواعد وسير العمل، واجعل استجابات الخادم تظهر حيث يمكن للمستخدمين التصرف عليها.
الأسئلة الشائعة
قم بتوحيدها عندما ترى نفس التسمية، النص المساعد، علامة الحقل المطلوب، المسافات، وتنسيق الأخطاء يتكرر عبر الصفحات. إذا كان أي تغيير "صغير" يقتضي تعديل العديد من الملفات، فستوفر لك طبقة BaseField مشتركة وعدد قليل من مكونات الإدخال المتناسقة الكثير من الوقت.
اجعل مكون الحقل بسيطًا: يعرض التسمية، عنصر التحكم، النص المساعد، الخطأ، ويصدر تحديثات القيمة. احتفظ بالمنطق العابر للحقول، القواعد الشرطية، وكل ما يعتمد على قيم أخرى في النموذج الأب أو طبقة التحقق حتى يبقى الحقل قابلًا لإعادة الاستخدام.
استخدم مفاتيح ثابتة تطابق حمولة الـ API افتراضيًا، مثل first_name أو billing.address.zip. هذا يجعل التحقق وتعيين أخطاء الخادم مباشرًا لأنك لا تحتاج لترجمة الأسماء بين الطبقات باستمرار.
افتراض بسيط: جسم حالة واحد يحتوي على values وerrors وtouched وdirty وdefaults. عندما تقرأ وتكتب كل المكونات عبر نفس الشكل، يصبح سلوك إعادة التعيين والإرسال متوقعًا وتتجنب أخطاء "إعادة التعيين الجزئي".
اضبط كل من values وdefaults من نفس بيانات التحميل. ثم يجب أن ينسخ reset() القيم من defaults إلى values ويمسح touched وdirty وerrors حتى تعود الواجهة لتطابق ما أرجعه الخادم آخر مرة.
ابدأ بقواعد بسيطة كدوال مفصولة مفاتيحها هي نفس مفاتيح النموذج. أعد رسالة واحدة واضحة لكل حقل (الفشل الأول) حتى تبقى الواجهة هادئة ويعرف المستخدم ما يجب إصلاحه أولًا.
تحقق معظم الحقول عند الخروج من الحقل (blur)، ثم تحقّق كل شيء عند الإرسال كفحص نهائي. استخدم التحقق عند التغيير فقط عندما يفيد حقًا (مثل قوة كلمة المرور) حتى لا يعاقب المستخدم أثناء الكتابة.
نفّذ الفحوصات غير المتزامنة عند الخروج أو بعد تأخير قصير، واعرض حالة "جارٍ التحقق" واضحة. وكن قادرًا على إلغاء أو تجاهل الطلبات القديمة حتى لا تُستبدل الاستجابات البطيئة أخطاء أحدث وتُربك المستخدم.
وحّد كل صيغة تأتي من الخادم إلى شكل داخلي واحد مثل { fieldErrors: { key: [messages] }, formErrors: [messages] }. استخدم نمط مسار واحد (الترميز بنقاط مفيد) حتى يقرأ الحقل address.street دومًا fieldErrors['address.street'] بدون حالات خاصة.
اعرض الأخطاء العامة أعلى النموذج، ووضع أخطاء الحقول بجانب المدخل المعني. بعد فشل الإرسال، ركّز أولًا على الحقل الذي به خطأ واحذف خطأ الخادم لذلك الحقل بمجرد أن يبدأ المستخدم بتعديله مجددًا.


