المحتوى عن 'واجهة رسومية'.



مزيد من الخيارات

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المُحتوى


التصنيفات

  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • نصائح وإرشادات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • التجارة الإلكترونية
  • الإدارة والقيادة
  • مقالات ريادة أعمال عامة

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
  • HTML
    • HTML5
  • CSS
  • SQL
  • سي شارب #C
    • منصة Xamarin
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • Sass
    • إطار عمل Bootstrap
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • برمجة أندرويد
  • لغة Swift
  • لغة R
  • لغة TypeScript
  • سير العمل
    • Git
  • صناعة الألعاب
    • Unity3D
  • مقالات برمجة عامة

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • خواديم
    • الويب HTTP
    • قواعد البيانات
    • البريد الإلكتروني
    • DNS
    • Samba
  • الحوسبة السّحابية
    • Docker
  • إدارة الإعدادات والنّشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • مقالات DevOps عامة

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • التسويق بالرسائل النصية القصيرة
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح

التصنيفات

  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • مقالات عمل حر عامة

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
  • أندرويد
  • iOS
  • macOS
  • ويندوز

التصنيفات

  • شهادات سيسكو
    • CCNA
  • شهادات مايكروسوفت
  • شهادات Amazon Web Services
  • شهادات ريدهات
    • RHCSA
  • شهادات CompTIA
  • مقالات عامة

أسئلة وأجوبة

  • الأقسام
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة البرمجة
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات
    • أسئلة الشهادات المتخصصة

التصنيفات

  • ريادة الأعمال
  • العمل الحر
  • التسويق والمبيعات
  • البرمجة
  • التصميم
  • DevOps

تمّ العثور على 4 نتائج

  1. يحبّ المصممون استخدام المساحات البيضاء، ويريد أصحاب المواقع ملأها. قد تبدو المساحات البيضاء واحدة من أكثر الجوانب المثيرة للجدل في التصميم. لماذا هي مهمّة جدًا إذًا وكيف يمكننا أن نضمن استخدامها بأفضل طريقة ممكنة؟ المساحات البيضاء هي حجر البناء الأساسي للتصميم الجيّد. إنّها واحدة من أوائل الأمور التي يفكّر بها أيّ مصمم. ولكن بالنسبة إلى العديد من أصحاب المواقع، فإنّها بكلّ بساطة مجرّد إهدارٍ لمساحةٍ كان يمكن استخدامها بشكلٍ أفضل لإيصال الرسائل، الخدمات والمنتجات التي يريدونها. أرغب في هذا المقال في أنّ أشرح سبب أهميّة المساحات البيضاء وكيفيّة إبقاءها ضمن التصميم دون الإضرار بمهام العمل. وعلى كلّ حال وقبل أن أبدأ في ذلك، يجب علينا أن نوضّح ما نعنيه بـ"المساحات البيضاء". مالذي يعنيه المصممون بالمساحات البيضاء؟عندما يتحدّث المصممون عن المساحات البيضاء، فهم يعنون المساحة السلبية بذلك. بعبارةٍ أخرى فهم يقصدون المسافة بين العناصر على الشاشة. وهي ليست دائمًا "بيضاء". فقد تكون هذه المساحة ملوّنة أو خليطًا من الألوان، ولكن وفي كلتا الحالتين فهي مساحة ضمن تصميم لا تحتوي على أيّ عناصر. يمكنك بالأسفل أن ترى بعض الأمثلة على المساحات البيضاء في عدّة مواقع. الآن وبعد أن قمنا بتعريف مصطلح "المساحات البيضاء" بوضوح، فإنّ السؤال التالي سيكون: “لماذا هي مهمّة؟". لماذا المساحات البيضاء مهمّةالمساحات البيضاء هي عنصر أساسي لأيّ تصميم لسببٍ وجيه. إذا تمّ استخدامها بشكلٍ جيّد فيمكنها أن تحوّل من شكل التصميم وتوفّر له العديد من المزايا والمحاسن. بعض هذه المحاسن يكون جماليًا بحتًا بينما تمتلك غيرها أثرًا مباشرًا على فعالية موقعك. أشارك معكم أدناه 4 إيجابيات لهذا النوع الأخير: تحسين الوضوحأفضل ميّزة للمساحات البيضاء هي أنّها تزيد من الوضوح. تحتاج فقط إلى مقارنة الأمثلة الظاهرة أدناه والمستنقاة من http://alistapart.com/article/whitespace حول المساحات البيضاء لتلاحظ كيفّ أنّ استخدامها بشكلٍ جيّد يمكنه أن يحسّن بشكلٍ هائل من درجة وضوح موقعك: فهمٌ أعلىصدّق أو لا تصدّق، يمكن للمساحات البيضاء بين الفقرات وحول أقسام النصوص أن تساعد الناس على أن يفهموا ما يقرؤون بشكلٍ أفضل. وفقًا لدراسة في 2004، يمكن لهذا النوع من المساحات البيضاء أن يحسّن نسبة الفهم بنسبة 20% تقريبًا. تركيزٌ أفضليمكن للمساحات البيضاء أيضًا أن تكون طريقةً رائعة لجذب اهتمام المستخدمين إلى عنصر معيّن على الشاشة. بالنسبة إلى غير المصممين، فإنّ أسهل طريقة لجعل شيءٍ ما يجذب اهتمامًا أكبر هي عبر جعله أكبر. ولكن غالبًا ما يكون إحاطة العنصر بالمساحات البيضاء فعّالًا بنفس الدرجة. إيصال النبرة الصحيحةوأخيرًا، فإنّ استخدام المساحات البيضاء يمكن أن يكون طريقةً ممتازة لإيصال أناقة ونضارة وانفتاح التصميم. طبعًا، هذه ليست الأمور التي تريد إيصالها دومًا عبر تصميمك، ولكنّ عندما تكون هي ما تريده، فليس هناك شيءٌ أفضل من استخدام العديد من المساحات البيضاء في التصميم. أصبحت محاسن المساحات البيضاء واضحةً الآن. ولكن أحيانًا يحصل وأن يتم طرد المساحات البيضاء خارجًا من التصميم. ولمنع هذا فإنّه يجب علينا أن نفهم لما قد يحصل هذا وكيف نتغلّب عليه. أعداء المساحات البيضاء الثلاثأعتقد أنّه هناك ثلاث أعداء رئيسيين يمنعون من استخدام المساحات البيضاء ضمن التصميم. إذا كنتَ تفهم ما هي هذه الأشياء وكيف تتعامل معها، فحينها ستوفّر فرصة أكبر لتصميمك ليستخدم المساحات البيضاء التي يحتاجها. فلنبدأ بالحديث عن الطيّ (the fold). الطيّ The foldيتم طرد المساحات البيضاء خارج التصميم عادةً بسبب أنّ شخصًا ما ضمن المؤسسة يعتقد أنّ المستخدمين لا يقومون باستخدام شريط التمرير (scrollbar). النتيجة هي أنّهم يصرّون على وضع أكبر كمّية ممكنة من المحتوى في أعلى مكان ممكن على الصفحة مما يمنع من استخدام أيّ مساحات بيضاء ضمن التصميم. وعلى كلّ حال، فقد تم إثبات خطأ فكرة أنّ المستخدمين لا يقومون باستخدام شريط التمرير مبكّرًا في عام 1997، بل وأظهرت دراسات حديثة أنّ المستخدمين يقومون باستخدام شريط التمرير بكثرة للانتقال إلى نهاية الصفحات. بالإضافة إلى ذلك، فإنّه من المهم أن تتذكّر أننا لا نعرف النقطة التي سيقوم المستخدمون بالبدء فيها باستخدام شريط التمرير. يعتمد هذا على نوع نظام التشغيل، المتصفّح، دقّة الشاشة والعديد من العوامل الأخرى. في النهاية فإنّ القلق على فكرة "طيّ" الصفحات هي فكرة خاطئة. بعد قول هذا، فإنّه ما يزال من الجيّد أن تضمن أنّ الرسائل التي تحثّ المستخدمين على اتّخاذ إجراء بالإضافة إلى المحتوى موضوعةٌ في أعلى الصفحة. ولكن، هذا لا يعني أنّه يجب عليك تجاهل المحتوى الآخر ضمن الصفحة. أضف إلى ذلك أنّ وضع الكثير من المحتوى في رأس الصفحة وبدايتها سيقلل من أهمّية المحتوى الرئيسي لأنّه سيتم تجاهله في مقابل محتوىً مجاورٍ أقل كما وضّحنا في نقطة "زيادة الانتباه" في الأعلى. محاولة قول الكثيرسببٌ شائع آخر يتم من أجله عدم استخدام المساحات البيضاء ضمن التصميم هو وجود الرغبة في إيصال الكثير من المعلومات في وقتٍ واحد. يمتلك معظم أصحاب المواقع الكثير من الأشياء التي يريدون قولها ولكنّ المستخدمين لسوء الحظ لا يعيرون سوى القليل من الاهتمام. لذلك فإنّه من المهم بالنسبة لك أن تقوم بـ"صرف" هذا الاهتمام بشكلٍ حكيم. صفحتا جوجل وياهو الرئيسيتان هما مثالٌ جيّد على هذه المشكلة. تعرض كلا الشركتان خدماتٍ مشابهة. ولكنّهما تتخذان مسارًا مختلفًا لطريقة هيكلة صفحتيهما الرئيسيتين. كما يمكنك أن ترى من لقطات الشاشة التالية، تحاول ياهو جلب المستخدم لينظر إلى كلّ شيءٍ في وقتٍ واحد. بينما تعرف جوجل أنّ المستخدم لديه تركيز محدود معك ولذلك فإنّهم يركّزون على منتجهم الرئيسي أولًا – البحث. عبر النظر إلى كلتا الصفحتين فإنّك تدرك مباشرةً أيّ واحدة منهما هي الأكثر فعالية. لكي تستفيد من هذه الفكرة أقترح عليك(أو على أولئك الذين يعملون ضمن مؤسستك والذين يريدون دفع المزيد من المحتوى) أن تقوم بتحديد 15 نقطة لاهتمام المستخدم. كلّ عنصرٍ تقوم بإضافته إلى الصفحة يكلّف نقطةً واحدة. إذا كان عنصرٌ ما على الشاشة أكثر أهمّية بالنسبة لك من واحدٍ آخر فإنّك بحاجة إلى إعطائه المزيد من النقاط لتجعله بارزًا. بعددٍ قليل من النقط المتوفّرة فإنّه يصبح من الواضح بشكلٍ سريع أنّك لا تستطيع قول كلّ شيءٍ تريده على الصفحة الرئيسية، ولذا فإنّه لا يوجد حاجة لإخراج المساحات البيضاء من التصميم. السياساتبالطبع وحتّى في أحسن الأحوال في العالم فإنّ صاحب الموقع قد يضطر إلى إضافة الكثير من المحتوى إلى صفحةٍ ما بسبب سياساتٍ داخلية. عندما يصرّ أحدٌ ما أعلى منك ضمن المؤسسة أن يظهر محتوى مشروعه أو مشروعها بأكمله على الصفحة الرئيسية فإنّه هناك القليل مما يمكنك فعله. هذا هو المكان الذي يعرض فيه كتاب "Laws of Simplicity" بعض النصائح الرائعة. إذا كنت لا تستطيع إزالة قطعة معيّنة من المحتوى من الصفحة، فحينها حاول تقليصها أو إخفاءها. خذ على سبيل المثال الطريق الذي استخدمناه على صفحة موقع Wiltshire Farm Foods الرئيسية. لأسباب عدّة فقد تقرر أن تحتوي الصفحة الرئيسية على الطعام وأخبار الصحّة بغضّ النظر عنّ أنّ هذه المعلومات ستشوّش على الزائر أن يقوم باتخاذ الإجراء المطلوب منه (شراء وجبة) ولم يكن شيئًا تهتم به الشريحة الكبرى من المستخدمين. كان حلّنا هو توفير هذا المحتوى ولكن إخفاؤه إلّا في حال قرر المستخدم عرضه. قطعة صغيرة من شفرة جافاسكربت كانت كافية لتوسيع ذلك القسم عند طلب المستخدم. هذا أخفى ذلك المحتوى عن أولئك المستخدمين الغير مهتمين به وسمح للتصميم بأن يحتوي على المزيد من المساحات البيضاء. الخاتمةهناك جدالٌ بسيط حول ما إذا كانت المساحات البيضاء عبارةً عن أداة قيّمة في التصميم يمكن أن تجعل أيّ موقع يبدو أكثر فعالية. ما أراه هو أنّه لا حاجة لأن تكون هذه النقطة هي نقطة خلاف بين المصممين وأصحاب المواقع. أؤمن بأنّ أيّ تصميم سيكون قادرًا على استخدام المساحات البيضاء بشكلٍ يلائم العمل المطلوب منه تنفيذه. ولكن مالذي تعتقدونه أيها الأصحاب؟ مالمشاكل التي واجهتموها مع المساحات البيضاء؟ لماذا تعتقدون أنّ المساحات البيضاء ضمن التصميم مهمّة جدًا؟ أو لماذا لا تعتقدون ذلك؟ شاركونا آرائكم في التعليقات أدناه. تمّت ترجمة المقال: Why whitespace matters وبتصرّف لصاحبه Paul Boag. حقوق الصورة البارزة: Designed by Freepik.
  2. استكشف الأفكار باستخدام ورقة وقلمإنّ استخدام الورقة والقلم طريقة جيدة لبدء عمل سير الاستخدام ورسم السكتشات (جمع سكِتش sketch) غير الدقيقة للتصميم. ويتيح الورق -كوسيط للتصميم- مرونة كبيرة ويسمح لك باستكشاف الأفكار وتجربة المفاهيم. قم بحل المشاكل بحرية على الورق دون الاضطرار لأن تفكر بكيفية حل هذه المشكلة باستخدام التطبيقات أو النصوص البرمجية. يضمن لك رسم السكتشات بأن تنشئ عددًا كبيرًا من الأفكار في وقت قصير. لا تبدِ اهتماما كبيرًا لعدم دقة أو ترتيب سكتشاتـك. عليك ببساطة أن تحدد أفكارك المبدئية وأن تحدد المفاهيم. يمكنك لاحقًا أن تأخذ أفضل العناصر وترتب أفكارك. إحدى التقنيات المفضلة لدي هي أن أنسخ بعض سكتشاتـي على آلة تصوير الأوراق، وأن أقطعها إلى أجزاء أساسية -بما يتسق مع شرح Brad Frost في Atomic Design-، ومن ثم أبدأ بإثراء مفهوم التصميم وذلك بتجميع وإعادة ترتيب العناصر. شخصيًّا، أجد أن تَحْريك قصاصات الورق يسمح لي بتحديد النمط والتفكير بكيفية تفاعل المستخدم مع حلول التصميم وتفسيره لرسائلي. لقد بدأت حديثًا باستخدام حاسوب محمول متصل بـCreative Cloude لتوريد الـسكتشات بسرعة إلى التطبيقات لتحسينها أكثر ولعمل تصاميم أولية سريعة. تعتمد إعادتك وتقييمك لحلول التصميم الخاصة بك على التدريب. ارسم سكتشات يوميًا وبتكرار ونفّذ تصاميم أولية. اتبع نمط ABC والذي يعني (Always Be Creating). هرم التصميميساعدك رسم سكتشات وتكرارها مراراً على التقدم في هرم التصميم. يسمح لك هذا أن تسير بأفكارك وتصميمك من حلول غير تفصيلية إلى تفصيلية، وأن تفصل التصميم بما يتناسب مع رسالة التواصل أو المنتج الرقمي. يعتمد هرم التصميم على مفهوم التصميم المتكامل Total Design لـ Stuart Pugh الذي يقسم الأنشطة إلى ست مراحل. أما بالنسبة للتصاميم الرقمية، فقد بسطتها إلى: رسم سكتشات، عمل أطر مفرغة، تمثيل، عمل تصاميم أولية. تذكر أن السكتش لا يساوي الإطار المفرغ. تخط النصوص الحافظة للمكان. استخدم محتوى حقيقيايجب أن يبدأ تصميم أيّ حل رقمي بمحتوى نابع من الحقيقة. النصوص الحافظة للمكان مجرد تقدير لأي تصميم ممكن. يجب أن يشمل تصميمك سياقًا للمحتوى المقدم للمستخدمين (وللزبائن). يمكن أن يُفضي استخدام المحتوى الحافظ للمكان إلى اتخاذ قرارات تصميم خاطئة يمكن أن تؤثر على التصميم وعلى التطوير في المستقبل. لقد رأيت ما لا يعد من النماذج والتصاميم الأولية التي فيها عبارة "Bob Smith, job title here". استخدم محتوى حقيقيًّا لتعرف كيف سيبدو تصميمك متى تمّ إكماله. ستساعدك النسخة الحقيقية من المحتوى على تحديد طول مستطيلات الإدخال في نماذج الوِب، وطول الأقسام وأشرطة التمرير الجانبية. ستعطيك النصوص الحافظة للمكان (lorem ipsum) شعورًا مزيفًا بالأمن وستؤدي إلى افتراضات غير واقعية عن عمل التصميم الخاص بك. ستصمم لتصل إلى مقدار مثالي من النسخ أو المحتوى، والتي لا تحدث أيّ منها في العالم الحقيقيّ. قم باتخاذ قرارات التصميم التي تدعم المحتوى. التصميم يحدد كيفية العملإن البساطة هي الهدف عند تصميم الواجهات وتجربة المستخدم. إن مراجعة حالات الاستخدام وقصص العمل يمكن أن تساعد على تشكيل الواجهة والتخلص من النقاط غير السلسة في طريقة التفاعل بين المستخدم والتصميم. ولكننا ما زلنا لا نعرف بالضبط من سيكون المستخدم النهائيّ أو كيف سيتفاعل مع الواجهة. من المهم لنا كمختصين في تصميم الواجهات وتجربة المستخدم أن ننشئ واجهات ترضي احتياجات كلّ من المستخدمين المبتدئين والخبراء؛ واجهات يسهل تعلمها دون أن تكون متعالية على المستخدم. يتطلب منا الانتقال من النقطة أ إلى النقطة ب أن نصل جسرًا في الهوة بين المستخدم المبتدئ والمتقدم، وذلك باستخدام تلميحات بصرية وتغذية راجعة للمستخدمين المبتدئين، وإتاحة مزايا متقدمة يمكن أن يتعلمها ويستكشفها المستخدمون المتقدمون. اختبر الافتراضات في المتصفحاختبر مبكرًا. اختبر بكثرة. قدم سياقًا للاستخدام. ابن تصميمًا أوليًّا يمكن أن يستخدَم في المتصفحات أو الأجهزة المحمولة وذلك لاختبار افتراضات التصميم التي لديك عبر التصاميم الأولية وذلك للتحقق من أفكارك وحلولك. صمم -باستخدام التصاميم الأولية- تجربة استخدام لا تحتاج لتعلم مسبق، وإنشاء أدوات وواجهات لا يلاحظ المستخدمون أنهم يستخدمونه، الأدوات والتفاعلات التي تتحول إلى جزء من المستخدم. جهّز البيئة للتفاعل مع المستخدم، وللإبقاء على تفاعل مستمر بسيط وسريع وطبيعي. وبالتأكيد، عليك أن تصمم لشاشات اللمس. قائمة التحقق من أدوات تصميم تجربة المستخدم:قلم رصاص وممحاة.أقلام حبر شبه سائلة (جِل)، وهي المفضلة لدي.مسطرة.دفتر رسم سكتشات (إما بورق غير مسطور أو ورق مربعات).أقلام بتدرجات رمادية.شبلونة رسم مفرغة.قصاصات ورقية ملونة.أقلام (ماركَر).هل هناك شيء آخَر ترغب بإضافته إلى هذه القائمة؟ أخبرنا في التعليقات. رحلة تصميم موفقة! ترجمة -وبتصرف- للمقال: Sketch, Iterate, Repeat: Prototyping Your Website Design لصاحبه: Andrew Smyk. حقوق الصورة البارزة: Designed by Freepik.
  3. تتطور أدوات التصميم المبدئي (prototype) للواجهات الرسومية UI بسرعة. لقد أتى إصدار فوتوشوب 2015 محمّلًا بمزايا جيدة تتعلق بـPreview CC الذي يسمح للمصممين بعرض ألواح التصميم الخاصة بهم وكذلك تراكيب الطبقات (layer comps) على الأجهزة. إن رؤية العمل ضمن سياقه على الأجهزة طريقة ثمينة لتقييم وتحسين المفهوم المتعلق بالتصميم. الوصول بالعمل إلى شاشات الأجهزة ذات العلاقة لهو مفتاح الوصول إلى توجهات تقديم المحتوى (content first approaches). التصميم الأولي الرقمي هام للمراحل اللاحقة، حيث يتم تحسين العمل وتطبيق التصميم المرئيّ عليه. سنناقش في هذا المقال الطرق المتبعة في المراحل الأولى للتصاميم الأولية الأقل دقّة التي يمكنك أن تطبقها قبل استخدام الأدوات الرقميّة، إضافة إلى ما عليك أن تبقيه في بالك عند عمل تصميم أولي لواجهة مستجيبة وواجهة تطبيق للأجهزة الكفيّة. ما هو التصميم الأولي (prototype)؟التعريف المفضل لدي لكلمة prototype تأتي من المصمم Adam St. John Lawrence: يعدّ المصممون مهارة التصميم الأوليّ مهارة أساسيّة، حيث يسمح التصميم الأولي باستكشاف أفكار عديدة بسرعة لعرض المفاهيم على زبائننا بدلًا من أن نصفها لهم، وأن نختبر التصاميم في مراحلها الأولى. الدقّة العالية والمنخفضةإن عملية التصميم التي تشمل حلقة من التصميم الأولي، والاختبار، ومعاودة الكرّة، تتيح أفضل فرصة ممكنة للحصول على منتج نهائي جيّد. دقّة التصميم الأولي ستزداد تدريجيًّا مع الوقت في المشروع، حيث تتضح الأفكار أكثر ويقترب الفريق أكثر نحو شيء جاهز للاستخدام. الطرق الأسرع والأرخص والأسهل في التنفيذ هي الأفضل في بداية المشروع. يجب أن تتطور دقة التصميم الأولي مع الوقت. لقد تم اقتباس المخطط أعلاه من Scott Klemmer. عمل سكتش على الورق سكِتشات المراحل الأولى تستعرض تجربة المستخدِم لتطبيق جهاز محمول. إن عمل سكتشات لهو من تقنيات التصميم الأولي الأكثر بساطة. السكتش (sketch، وجمعه سكِتشات) لا يُنتج بالضرورة تصميمًا أوليًّا، ولكن السكتشات هي لبنات البناء الأولى، وهي النسخة الأولى ومرحلة البداية للشيء الذي تعمل عليه. ليس من الضروري أن تجيد الرسم، ولا يتعلق الأمر بجعل الشيء يبدو جميلًا. إن المربعات والمستطيلات البسيطة ممتازة لرسم سكتشات غير دقيقة. يتعلق رسم السكتش في هذه المرحلة بالعمل على أفكار كثيرة بسرعة. ورسم السكِتشات (sketches) أداة تسمح بمشاركة الرؤية مع المعاونين (شركاء، زبائن، زملاء، ...). نصائح للتصاميم الأولية للواجهات المستجيبة وواجهات الموبايل: يمكن أن تساعدك الرسومات البسيطة للواجهة (UI stencils) بأن ترسم سكِتشًا لعناصر الواجهة الشائعة الخاصة بمنصة معينة بسرعة.سيساعدك رسم عدة أحجام للشاشات بجانب بعضها بعضًا للمقارنة على التفكير في التصميم عبر أحجام شاشات متعددة. ارسم سكِتشاتك بحجم صغير ومتوسط وكبير بجانب بعضها، ولا تنتقل إلى صفحة أخرى قبل أن تأخذ جميع أحجام الصفحة التي تعمل عليها بعين الاعتبار.رسم سكِتش في نطاق العالم الحقيقي طريقة ممتازة لتكون واقعيًا فيما يتعلق بتناسب الحجم، وخاصة على الشاشات الصغيرة.القوالب الموجهة لشاشات اللمس على الأجهزة المحمولة رائعة للتأكد من أنها تناسب الفئة المستهدفة من مستخدمي الأجهزة ذات شاشات اللمس، حيث تكون أجهزتهم كبيرة بما يكفي لتناسب التصميم عند الاستمرار في العمل عليه. رسم سكِتشات على اللوح يسمح رسم السكِتش على اللوح بجعل العمل مرئيًّا لفريق أكبر. رسم سكِتشات على اللوح طريقة رائعة للعمل. هذا الوسيط (اللوح) على وجه الخصوص مناسب لجلسات رسم السكِتشات التعاونية. تشجّع المساحة الكبيرة والأقلام كبيرةُ الحجمِ على القيام بعمل أكبر وأقرب إلى مفهوم "سكِتش"، ويمكن أن يساعد أعضاء الفريق الخجولين أو المترددين على أن يشاركوا. إن العمل على لوح يعني أن أكثر من شخص يمكن أن يعملوا على نفس السكِتش أو الفكرة. يسهُل مسح السكِتشات المرسومة على لوح والإضافة إليها والعمل عليها، مما يعني أن أعضاء الفريق سيتمكنون من أن يعملوا على التفاصيل معاً وبسرعة. نصائح للتصاميم الأولية للواجهات المستجيبة وواجهات الموبايل: أبقِ في بالك أن العمل على لوح بحجم كبير لا يعبر عن القيود التي تواجهك على شاشات أصغر. بمجرد أن يتم تطوير فكرة، حاول التبديل إلى رسم سكتشات بمقياس رسم 1:1 على الورق أو باستخدام مناطق محجوزة مسبقًا على اللوح لتقييد العمل.لا تنسَ أن توثِّق السكتشات! خذ صورًا للتقدم قبل أن تنتقل إلى شيء آخَر.للعمل على تصاميم مستجيبة، ارسم سكتشات لإصدارات صغيرة ومتوسطة وكبيرة لنفس الصفحة جنبًا إلى جنب.عمل تصاميم أوليّة على الورق: تصميم أولي بسيط على الورق في بداية العمل. يمكن للتصميم الأولي على الورق أن يتراوح مستويات مختلفة من الدقّة، من مجموعة سكتشات على أوراق منفصلة، إلى عمل تفصيليّ على الورق، إلى أُطُر مفرغة يمكن تصميمها حاسوبيًّا ثم طباعتها. اختبار التصاميم الأولية على الورق طريقة سهلة وغير مكلفة للتحقق من الأفكار. يمكنك أن تسأل المستخدمين أن يعبروا ببساطة عن ما يرونه، أو أن يقوموا بعمل اختبار يتعلق بالوظيفة. يمكن للإنسان أن يعمل كحاسوب وأن يُبدِل الصفحات أو يخرج نوافذ منبثقة وأن يتفاعل مع المستخدم بشكل عام. هذه طريقة فعَالة للغاية، ويتفاعل معها المشاركون بجدية. تُدعى هذه الطريقة من التصاميم الأولية لـ"ساحر أوز" (بالإنجليزية: “Wizard of Oz prototyping”، كما في الرواية الأمريكيّة). نصائح للتصاميم الأولية للواجهات المستجيبة وواجهات الموبايل: يُمكِن للودجات (جمع وِدجَة، بالإنجليزية widget) أن تُمثَّل بورقة أو بطاقة.يُفضَّل العمل على التحجيم في هذه المرحلة، وخاصة إذا كنت تنوي اختبار الواجهة باستخدام النماذج الورقية.أنشئ إطارات أجهزة بالورق أو الورق المقوّى لعرض الصفحات بداخلها.أنشئ قوائم منسدلة وعناصر تفاعلية أخرى بقصّ وطيّ قطع الورق، حيث يمكن إلصاقها باستخدام اللاصق أو تمريرها عبر فتحات في الصفحة.الصق شاشات النموذج الأوليّ الورقيّة بأجهزة حقيقية لأخذ فكرة عن كيفيّة استخدام الناس للجهاز في سياق الواقع، وإلى أيّ حدّ يمكنهم أن يصلوا في الشاشة عند إمساكهم للجهاز في وضعيات مختلفة.التفاعل بلعب الأدوارالتفاعل جزء مهم من تجربة المستخدم (UX). تطوير هذه النماذج الأولية رقميًّا سيأخذ كثيرًا من الوقت ولن يكون واقعيًّا في المراحل الأولى من المشروع. من الطرق السريعة والمجدية اقتصاديًّا وممتعة لتجربة سلاسة التصميم والتفاعل معه: تمثيل الأدوار. أحد الأشخاص يمثل دور الصفحة أو التطبيق، والآخَر يلعب دور المستخدِم. يُساعد التفكير في تجربة المستخدم كمحادثة أو تفاعل ثنائيّ الاتجاه على التأكد من أنّ التجربة تتبع تسلسلًا منطقيًّا بشريًّا. يمكن أيضًا أن تكشف التعبيرات المتخصّصة أو التي يحتمل أن تكون مُبهمَة. نصائح للتصاميم الأولية للواجهات المستجيبة وواجهات الموبايل: فكّر بالرسائل أو لغة التفاعل الخاصّة بالمنصة (البيئة، نظام التشغيل، الجهاز ...) عند تصميم واجهات الموبايل.خذ بعين الاعتبار الاختلاف في الشكل العام بين الأحجام المختلفة للشاشات، وكيف يمكن له أن يؤثر على المسار المحادثة/التفاعل.خلاصةها قد عرفت! ارسم سكتش، اختبر التصميم على الورق، وقم بتمثيل الأدوار التي تتعلق بطريقة التفاعل لتقفز إلى بداية متقدمة في إنشاء تجربة مستخدم ممتازة. ترجمة -وبتصرف- للمقال: Early Stage UX Prototyping: Tips for Mobile and Responsive Design لصاحبه: Linn Vizard. حقوق الصورة البارزة: Designed by Freepik.
  4. يعتبر React.js -على حداثته- من أقوى أطر عمل Javascript (بعضهم قد يسميه مكتبة وليس إطار عمل) لبناء الواجهات الرسومية على الويب، حيث طبّق أفكارًا جديدة في هذا المجال، جعلت شِفرة الواجهات البرمجية أكثر نظافة، سرعة وأكثر قابلية للصيانة. يسمح لك React ببناء الواجهة الرسومية في مجموعة مكونات، كل مكوّن عبارة عن سرد لهيكلة ومنطق المكون، إذا تمزج بين شِفرة HTML مخصصّة وشِفرة جافاسكربت تصف سلوك ذاك المكون، ليكون قائما بذاته وقابلا لإعادة الاستعمال. إطار عمل React مُطور من طرف شركة فيس بوك (Facebook)، وقد يكفيك ثقة ويجذب انتباهك بمجرد أن تعرف أن فيس بوك نفسها تستخدم React في واجهتها البرمجية على موقع Facebook نفسه! يمكنك فتح موقع Facebook وعرض شفرة HTML الخاصة به والبحث عن كلمة react للتأكد بنفسك. سنقوم في هذا الدرس بإنشاء مُربَّع تعليقات بسيط وفعَّال بإمكانك وضعه في مدوَّنتك، سيكون المُربَّع عبارة عن نُسخة مُجرَّدة من التعليقات الآنية التي تُقدمها لك تعليقات Disquse ،LiveFyre أو فيس بوك. ستجد في نهاية الدَّرس أنَّ لديكَ مُربَّع تعليقات يوفِّر ما يلي: عرض لجميع التعليقات.نموذج لإرسال تعليق.خُطَّافات لتوفير مُنتهى خلفي مُخصَّص custom backend.سوف يحتوي مُربَّع التعليقات كذلك على بعض المزايا اللَّطيفة: تعليق مُحسَّن: تظهر التَّعليقات في القائمة قبل أن يتمّ حفظها على الخادم وبناءً عليه تظهر التَّعليقات في التوِّ واللَّحظة.تحديثات حيَّة: تظهر تعليقات المستخدمين الآخرين في عرض التَّعليقات في نفس وقت الإرسال.هيئة Markdown: يُمكن للمستخدمين استخدام Markdown لتهيئة نصوصهم.هل ترغب في تخطِّي كل هذا ومعاينة المصدر؟ كل شيء موجود على GitHub. تشغيل الخادمرغم أنَّه ليس من الضروري أن تبدأ بهذا الجزء من الدرس إلَّا أنَّنا سنقوم في وقت لاحق بإضافة وظائف تتطلَّب المُشاركة POST إلى خادم قيد التشغيل. إذا كُنتَ واثقٌ من أنّك على دراية بهذا الأمر وترغب في إنشاء خادمك الخاص يُمكنكَ القيام بذلك. ولِمَن يُريد التَّركيز على تعلُّم React دون الحاجة إلى القلق بشأن جوانب الخادم، فلقد كتبنا خوادم بسيطة بعددٍ من اللُّغات: Python ،Ruby ،Go، Node.js و PHP. كلُّ هذا مُتاح على GitHub. يُمكن الاطِّلاع على المصدر أو تحميل ملفّ مضغوط للبدء. للبدء بتطبيق هذا الدَّرس، كلّ ما عليكَ فعله هو بداية تحرير public/index.php. البدءسنستخدم لهذا الدرس ملفَّات JavaScript سبق إنشاؤها على شبكة توصيل مُحتوى CDN. قم بفتح المُحرِّر المفضَّل لديك وقم بإنشاء مُستند HTML جديد: <!-- index.html --> <!DOCTYPE html> <html> <head> <title>Hello React</title> <script src="https://fb.me/react-0.13.3.js"></script> <script src="https://fb.me/JSXTransformer-0.13.3.js"></script> <script src="https://code.jquery.com/jquery-2.1.3.min.js"></script> </head> <body> <div id="content"></div> <script type="text/jsx"> // Your code here </script> </body> </html>سيتمّ كتابة شفرات JavaScript في وسم السكربت هذا طوال الفترة المتبقية من الدرس. مُلاحظة: قُمنا بإدراج jQuery هُنا لأننا نٌريد تبسيط الشَّفرات لاستدعاءات Ajax في المُستقبل، ولكنَّها ليست إلزاميَّة لعمل React. مُكوِّنكَ الأوَّلتتمحور الفكرة الأساسيَّة لـ React حول كل شيءٍ له علاقة بالمُكوِّنات التركيبيَّة القابلة للتَّشكيل modular, composable components. سنستخدم بنية المُكوٍّنات التالية لمثال مُربَّع التَّعليقات لهذا الدرس: - CommentBox - CommentList - Comment - CommentFormسنقوم الآن ببناء المُكوِّن CommentBox وما هو إلَّا وسم بسيط: // tutorial1.js var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> Hello, world! I am a CommentBox. </div> ); } }); React.render( <CommentBox />, document.getElementById('content') );لاحظ أن أسماء عناصر HTML تبدأ بحرف صغير في حين أن أسماء فئات React تبدأ بحرف كبير. 1. صياغة JSXستُلاحظ أوَّل ما تلاحظ تلكَ الصياغة المُشابهة لـ XML في شفرة JavaScript. لدينا precompiler بسيط يُترجم الجُملة البسيطة Syntactic Sugar إلى شفرات JavaScript المُجرَّدة هذه: // tutorial1-raw.js var CommentBox = React.createClass({displayName: 'CommentBox', render: function() { return ( React.createElement('div', {className: "commentBox"}, "Hello, world! I am a CommentBox." ) ); } }); React.render( React.createElement(CommentBox, null), document.getElementById('content') );إنَّ استخدام صياغة JSX اختياري ولكن وجدنا أنَّها أسهل استخدامًا من شفرات JavaScript مُجرَّدة. يُمكن قراءة المزيد في مقال صياغة JSX 2. ماذا يحدث هنانقوم بتمرير بعض الوظائف في كائن JavaScript إلى دالَّة ()React.createClass لإنشاء مُكوِّن React جديد. أهم هذه الوظائف ما تُسمَّى تصيير render والتي تُعيد شجرة من مُكوِّنات React والتي في نهاية المطاف ستقوم بالتصيير عبر HTML. لا تُعتبر وسوم عُقَد نموذج كائن مُستند DOM فعليَّة، وإنَّما هي تمثيلات من مُكوِّنات div الخاصَّة بـ React. يُمكنكَ اعتبارها كوسوم أو قطع من البيانات والتي يعرف React كيفيَّة التعامل معها. React آمن. لا نقوم بتوليد سلاسل HTML لذلك فإن حماية XSS تُعتبر الافتراضيَّة. لا يجب عليكَ إعادة شفرات HTML قياسيَّة. وإنَّما يُمكنكَ إعادة شجرة من المُكوِّنات التي قُمتَ (أو شخص آخر قام) ببنائها. هذا ما يجعل React قابلة للتَّشكيل composable: وهي عقيدة أساسيَّة في الواجهات الأماميَّة القابلة للصّيانة. يقوم ()React.render بتمثيل المُكوِّن القاعدي، بدء عمل الإطار، ثم إدخال الوسوم إلى عنصر نموذج كائن مُستند خام، يتمّ تقديم تلك الوسوم كمُعطى ثاني . تركيب المُكوِّناتسنُنشيء الآن هياكل بناء لكلٍّ من المُكوِّنين CommentList وCommentForm والتي ستكون -مرَّة أخرى- عبارة عن وسوم بسيطة. أضِف هذين المُكوِّنين إلى ملفِّك مع الحفاظ على تعريف commentBox الحالي واستدعاء React.render: // tutorial2.js var CommentList = React.createClass({ render: function() { return ( <div className="commentList"> Hello, world! I am a CommentList. </div> ); } }); var CommentForm = React.createClass({ render: function() { return ( <div className="commentForm"> Hello, world! I am a CommentForm. </div> ); } });ما سنقوم بعمله الآن هو تحديث مُكوِّن CommentBox لاستخدام المُكوِّنات الجديدة: // tutorial3.js var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList /> <CommentForm /> </div> ); } });لاحظ كيف تمَّ مزج وسوم HTML والمُكوِّنات التي قُمنا ببنائها. إنَّ مُكوِّنات HTML ما هي إلَّا مُكوِّنات React مُنتظمة، تمامًا مثل تلك التي تقوم بتعريفها ولكن مع فارق واحد. سيقوم مترجم JSX تلقائيًا بإعادة كتابة وسوم HTML إلى تعبيرات React.createElement() tagName وترك كل شيء على حدة. وهذا لمنع حدوث التَّلوّث في مساحة الاسم العموميَّة global namespace. استخدام الخصائصسنقوم الآن بانشاء مُكوِّن Comment، والذي سوف يعتمد على البيانات التي تمَّ تمريرها إليه من المُكوِّن الأساسي. يتمّ اتاحة البيانات التي تمّ تمريرها من مُكوِّن أساسي كـ "خاصيَّة" في المُكوِّن الفرعي. ويتمّ الوصول إلى هذه "الخصائص" من خلال this.props. يُمكننا باستخدام الخصائص props قراءة البيانات التي تمّ تمريرها إلى Comment من CommentList، وتصيير بعض الترميزات: // tutorial4.js var Comment = React.createClass({ render: function() { return ( <div className="comment"> <h2 className="commentAuthor"> {this.props.author} </h2> {this.props.children} </div> ); } });يُمكنكَ وضع نصّ أو مُكوِّنات React في الشَّجرة وذلك بإحاطة تعبير JavaScript بأقواس داخل JSX (إما كخاصيَّة أو كمُكوِّن فرعي). نقوم بالوصول إلى خاصيَّات مُسمَّاه تمّ تمريرها إلى عنصر كمفاتيح على this.props وأيّ عناصر مُتداخلة كما this.props.children. خصائص المُكوِّننحتاج الآن وبعد أن قمنا بتحديد مُكوِّن Comment إلى تمرير اسم الكاتب ونصّ التعليق إلى هذا المُكوِّن. يسمح لنا هذا بإعادة استخدام نفس الشَّفرة لكلِّ تعليق مُختلف. لنقوم الآن بإضافة بعض التَّعليقات داخل مُكوِّن CommentList: // tutorial5.js var CommentList = React.createClass({ render: function() { return ( <div className="commentList"> <Comment author="Pete Hunt">This is one comment</Comment> <Comment author="Jordan Walke">This is *another* comment</Comment> </div> ); } });لاحظ أنَّنا قد قُمنا بتمرير بعض البيانات من مُكوِّن CommentList الأساسي إلى مُكوِّنات Comment الفرعيَّة. مرَّرنا على سبيل المثال Pete Hunt (عن طريق خاصيَّة) وThis is one comment (عن طريق عُقدة فرعيَّة تُشبه XML) إلى Comment الأوَّل. وكما ذكرنا بالأعلى فإنَّ مُكوِّن Comment سيعمل على الوصول إلى هذه الخصائص من خلال this.props.author، وthis.props.children. إضافة MarkdownMarkdown هي طريقة بسيطة لتهيئة مُضمّنة inline لنصِّك. على سبيل المثال، احاطة النص بعلامة النجمة (*) سيقوم بتأكيده. أولًا، أضِف مكتبة الطرف الثالث marked إلى تطبيقك. Marked هي مكتبة JavaScript تقوم بأخذ نص Markdown وتُحوِّله إلى صيغة HTML خام. هذا الأمر يتطلَّب وسم سكربت في قسم head (قُمنا بادراجه بالفعل في أرضيَّة React): <!-- index.html --> <head> <title>Hello React</title> <script src="https://fb.me/react-0.13.3.js"></script> <script src="https://fb.me/JSXTransformer-0.13.3.js"></script> <script src="https://code.jquery.com/jquery-2.1.3.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js"></script> </head>سنقوم بعد ذلك بتحويل نصّ التَّعليق إلى Markdown ومن ثمَّ إخراجه: // tutorial6.js var Comment = React.createClass({ render: function() { return ( <div className="comment"> <h2 className="commentAuthor"> {this.props.author} </h2> {marked(this.props.children.toString())} </div> ); } });كل ما فعلناه هنا هو استدعاء مكتبة marked. نحتاج إلى تحويل this.props.children من نصّ React مُحاط إلى سلسلة خام يُمكن لمكتبة marked فهمها ولذلك فإننا نقوم بستدعاء دالَّة ()toString. لكن لدينا مشكلة وهي أنَّه يتمّ إظهار وسوم HTML الموجودة في التَّعليقات بالشكل التَّالي في المُتصفح: This is another comment. هذا الأمر هو حماية React لك من هجوم XSS. هُناك طريقة للالتفاف على ذلك، ولكنَّ إطار العمل يُحذِّرُكَ من استخدامها: // tutorial7.js var Comment = React.createClass({ render: function() { var rawMarkup = marked(this.props.children.toString(), {sanitize: true}); return ( <div className="comment"> <h2 className="commentAuthor"> {this.props.author} </h2> <span dangerouslySetInnerHTML={{__html: rawMarkup}} /> </div> ); } });هذه الشَّفرات هي API خاصّ والذي عمدًا يجعل من الصَّعب إدراج شفرات HTML خام، في حالتنا بالنِّسبة لمكتبة marked فإنَّنا سنقوم بالاستفادة من هذا المنفذ الخلفيّ. تذكَّر: باستخدامك لهذه الميزة فإنَّك تعتمد على مكتبة marked أن تكون آمنة. نقوم في هذه الحالة بتمرير sanitize: true التي تطلب من مكتبة marked تنفيذ أي وسم HTML في المصدر بدلًا من تمريره دون تغيير. إضافة نموذج البياناتحتَّى الآن فإنَّنا نقوم بإدراج تعليقات مُباشرة في شفرات المصدر. بدلًا من ذلك، سنقوم بتصيير بضع من بيانات JSON في قائمة التعليق. يأتي هذا من الخادم في نهاية المطاف، ولكن في الوقت الراهن سنكتبها نحن في المصدر: // tutorial8.js var data = [ {author: "Pete Hunt", text: "This is one comment"}, {author: "Jordan Walke", text: "This is *another* comment"} ];الآن نحنُ بحاجة إلى إدخال هذه البيانات في مُكوِّن CommentList بطريقة نموذجيِّة. قُم بتعديل CommentBox واستدعاء ()React.render لتمرير هذه البيانات إلى CommentList عن طريق الخصائص props: // tutorial9.js var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList data={this.props.data} /> <CommentForm /> </div> ); } }); React.render( <CommentBox data={data} />, document.getElementById('content') );الآن حيثُ أنَّ البيانات مُتاحة في CommentList، سوف نقوم بتقديم التَّعليقات بطريقة ديناميكيَّة: // tutorial10.js var CommentList = React.createClass({ render: function() { var commentNodes = this.props.data.map(function (comment) { return ( <Comment author={comment.author}> {comment.text} </Comment> ); }); return ( <div className="commentList"> {commentNodes} </div> ); } });هذا كل شيء. الاستدعاء من الخادمسنعمل الآن على استبدال البيانات الثَّابتة ببعض البيانات الديناميكيَّة من الخادم. يتمّ ذلك بإزالة خاصيَّة البيانات data prop واستبدالها بعنوان URL للجلب: // tutorial11.js React.render( <CommentBox url="comments.json" />, document.getElementById('content') );هذا المُكوِّن مُختلف عن المُكوِّنات السَّابقة حيثُ أنَّه سيضطر إلى إعادة تصيير نفسه. لن يحتوي المُكوِّن على أيّ بيانات إلى أن يعود الطَّلب من الخادم، في هذه الحالة قد يحتاج المُكوِّن إلى تصيير بعض التَّعليقات الجديدة. الحالة التفاعليَّةقام كلّ مُكوِّن حتَّى الآن على أساس خصائصه بتصيير نفسه مرة واحدة. الخصائص props ثابتة: يتمّ تمريرها من المُكوِّن الأساسي و”مملوكة” من قبل المُكوِّن الأساسي كذلك. لتنفيذ التَّفاعلات، فإنَّنا نُقدِّم حالة قابلة للتغيير إلى المُكوِّن. حالة this.state هي خاصَّة بالمُكوِّن ويُمكن تغييرها من خلال استدعاء ()this.setState يقوم المُكوِّن بإعادة تقديم نفسه عند تحديث الحالة. وظائف ()render مكتوبة إلزاميًّا كدوال this.props وthis.state. يضمن إطار العمل أن تكون واجهة المستخدم دائمًا مُتَّسِقَة مع المُدخَلات. عندما يقوم الخادم بجلب بيانات سنقوم نحن بتغيير بيانات التعليق لدينا. لنُضيف الآن مصفوفة من بيانات التَّعليق كحالة للمُكوِّن CommentBox: // tutorial12.js var CommentBox = React.createClass({ getInitialState: function() { return {data: []}; }, render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList data={this.state.data} /> <CommentForm /> </div> ); } });يتمّ تنفيذ دالَّة ()getInitialState مرَّة واحدة فقط خلال دورة حياة المُكوِّن كما أنَّها تبدأ الحالة الأوليَّة للمُكوِّن. تحديث الحالةنُريد عند إنشاء المُكوِّن لأوَّل مرَّة أن نحصل على (GET) بعض بيانات JSON من الخادم وتحديث الحالة لتعكس أحدث البيانات. هذا من شأنه أن يكون نقطة نهاية ديناميكيَّة لو كان الأمر في تطبيق حقيقي، ولكن سنستخدم لهذا المثال ملف JSON ثابت لابقاء الأمور بسيطة: // tutorial13.json [ {"author": "Pete Hunt", "text": "This is one comment"}, {"author": "Jordan Walke", "text": "This is *another* comment"} ]سنقوم باستخدام مكتبة jQuery للمساعدة في عمل طلب غير متزامن asynchronous request إلى الخادم. مُلاحظة: حيثُ أنَّ هذا الأمر أصبح تطبيق AJAX فإنَّك سوف تحتاج لتطوير تطيبقك باستخدام خادم ويب بدلًا من أن ملف موجود في نظام ملفاتك. قدَّمنا -كما هو مذكورٌ بالأعلى- العديد من الخوادم التي يُمكنكَ استخدامها على GitHub. توفر تلك الخوادم التأدية الوظيفيَّة التي تحتاجها لبقيَّة هذا الدرس. // tutorial13.js var CommentBox = React.createClass({ getInitialState: function() { return {data: []}; }, componentDidMount: function() { $.ajax({ url: this.props.url, dataType: 'json', cache: false, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList data={this.state.data} /> <CommentForm /> </div> ); } });وظيفة componentDidMount هنا هي وظيفة تُستدعى تلقائيًا بواسطة React عندما يتمّ تصيير مُكوِّن. مفتاح التَّحديثات الديناميكيَّة هو استدعاء دالَّة ()this.setState. نقوم باستبدال مصفوفة التَّعليقات القديمة بواحدة جديدة من الخادم وتقوم واجهة المستخدم بتحديث نفسها تلقائيًا. بسبب هذا التفاعل، يُعتبر التغيير لإضافة تحديثات حيَّة طفيفًا. سوف نستخدم أسلوب بسيط في هذا الدَّرس ولكن لكَ الحُريَّة في استخدام WebSockets أو غيرها من التكنولوجيَّات. // tutorial14.js var CommentBox = React.createClass({ loadCommentsFromServer: function() { $.ajax({ url: this.props.url, dataType: 'json', cache: false, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, getInitialState: function() { return {data: []}; }, componentDidMount: function() { this.loadCommentsFromServer(); setInterval(this.loadCommentsFromServer, this.props.pollInterval); }, render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList data={this.state.data} /> <CommentForm /> </div> ); } }); React.render( <CommentBox url="comments.json" pollInterval={2000} />, document.getElementById('content') );كل ما فعلناه هنا هو نقل استدعاء AJAX إلى وظيفة مُستقلَّة واستدعائها عند تحميل المُكوِّن الأوَّل واستدعائها كلّ ثانيتين بعد ذلك. حاول تشغيل هذا في مُتصفِّحك وتغيير ملف comments.json. في غضون ثانيتين ستظهر لكَ التغييرات. إضافة تعليقات جديدةحان الآن الوقت لبناء النموذج. على مُكوِّن CommentForm أن يسأل المُستخدم عن اسمه ونصّ التَّعليق، ثم يقوم بإرسال طلب إلى الخادم لحفظ التعليق. // tutorial15.js var CommentForm = React.createClass({ render: function() { return ( <form className="commentForm"> <input type="text" placeholder="Your name" /> <input type="text" placeholder="Say something..." /> <input type="submit" value="Post" /> </form> ); } });دعونا نجعل النموذج متجاوب. عندما يقوم المُستخدم بإرسال النَّموذج، يجب علينا مسحه clear، تقديم طلب إلى الخادم، ثُمَّ تحديث قائمة التعليقات. للبدء في تنفيذ هذا، سقوم بالاستماع إلى حدث ارسال النَّموذج ومسحه. // tutorial16.js var CommentForm = React.createClass({ handleSubmit: function(e) { e.preventDefault(); var author = React.findDOMNode(this.refs.author).value.trim(); var text = React.findDOMNode(this.refs.text).value.trim(); if (!text || !author) { return; } // TODO: send request to the server React.findDOMNode(this.refs.author).value = ''; React.findDOMNode(this.refs.text).value = ''; return; }, render: function() { return ( <form className="commentForm" onSubmit={this.handleSubmit}> <input type="text" placeholder="Your name" ref="author" /> <input type="text" placeholder="Say something..." ref="text" /> <input type="submit" value="Post" /> </form> ); } });1- الأحداث Eventsتقوم React بإرفاق مُعالجات الحدث في المُكوِّنات باستخدام اتفاقية التَّسمية camelCase. نقوم بإرفاق مُعالج onSubmit إلى النَّموذج الذي يعمل على مسح حقول النَّموذج عند إرساله مع إدخال صحيح. عليكَ استدعاء ()preventDefault بالحدث لمنع الإجراء الافتراضي للمُتصفِّح من اعتماد النَّموذج. 2- المراجع Refsنستخدم خاصيَّة ref لتعيين اسم للمُكوِّن الفرعي وthis.refs لارجاع المُكوِّن. يمكن أن نستدعي (React.findDOMNode(componentعلى مُكوّن للحصول على عنصر نموذج كائن مُستند المُتصفِّح الأصلي. 3- نداءات الخصائصعندما يُرسِل المُستخدم التَّعليق، فإنَّنا سوف تحتاج إلى تحديث قائمة التَّعليقات لتشمل التَّعليق الجديد. من الطبيعي أن تفعل كل هذا في مُكوِّن CommentBox حيث أنَّ المُكوِّن يمتلك الحالة التي تُمثِّل قائمة التَّعليقات. نحن بحاجة لتمرير البيانات من نُسخة المُكوِّن الفرعي الاحتياطيَّة إلى المُكوِّن. يتمّ فعل هذا في وظيفة render الخاصَّة بالأب عن طريق تمرير رد نداء جديد (handleCommentSubmit) في الابن ثُمَّ الزامها لحدث الابن onCommentSubmit. كُلَّما تم تشغيل الحدث، سيُنفَّذ الاستدعاء: // tutorial17.js var CommentBox = React.createClass({ loadCommentsFromServer: function() { $.ajax({ url: this.props.url, dataType: 'json', cache: false, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, handleCommentSubmit: function(comment) { // TODO: submit to the server and refresh the list }, getInitialState: function() { return {data: []}; }, componentDidMount: function() { this.loadCommentsFromServer(); setInterval(this.loadCommentsFromServer, this.props.pollInterval); }, render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList data={this.state.data} /> <CommentForm onCommentSubmit={this.handleCommentSubmit} /> </div> ); } });سوف نستدعي الآن النِّداء من CommentForm عندما يقوم المُستخدم بإرسال النَّموذج: // tutorial18.js var CommentForm = React.createClass({ handleSubmit: function(e) { e.preventDefault(); var author = React.findDOMNode(this.refs.author).value.trim(); var text = React.findDOMNode(this.refs.text).value.trim(); if (!text || !author) { return; } this.props.onCommentSubmit({author: author, text: text}); React.findDOMNode(this.refs.author).value = ''; React.findDOMNode(this.refs.text).value = ''; return; }, render: function() { return ( <form className="commentForm" onSubmit={this.handleSubmit}> <input type="text" placeholder="Your name" ref="author" /> <input type="text" placeholder="Say something..." ref="text" /> <input type="submit" value="Post" /> </form> ); } });الآن وبعد أن أصبح النِّداء في مكانه الصحيح، كل ما علينا القيام به هو الإرسال إلى الخادم وتحديث القائمة: // tutorial19.js var CommentBox = React.createClass({ loadCommentsFromServer: function() { $.ajax({ url: this.props.url, dataType: 'json', cache: false, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, handleCommentSubmit: function(comment) { $.ajax({ url: this.props.url, dataType: 'json', type: 'POST', data: comment, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, getInitialState: function() { return {data: []}; }, componentDidMount: function() { this.loadCommentsFromServer(); setInterval(this.loadCommentsFromServer, this.props.pollInterval); }, render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList data={this.state.data} /> <CommentForm onCommentSubmit={this.handleCommentSubmit} /> </div> ); } });تحديثات مُحسَّنةمشروعنا الآن كامل الوظائف ولكن من المُمل أن نقوم بانتظار الطَّلب حتَّى يكتمل قبل ظهور تعليقك في القائمة. يُمكننا إضافة هذا التَّعليق إلى القائمة لجعل التطبيق يعمل بشكلٍ أسرع. // tutorial20.js var CommentBox = React.createClass({ loadCommentsFromServer: function() { $.ajax({ url: this.props.url, dataType: 'json', cache: false, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, handleCommentSubmit: function(comment) { var comments = this.state.data; var newComments = comments.concat([comment]); this.setState({data: newComments}); $.ajax({ url: this.props.url, dataType: 'json', type: 'POST', data: comment, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, getInitialState: function() { return {data: []}; }, componentDidMount: function() { this.loadCommentsFromServer(); setInterval(this.loadCommentsFromServer, this.props.pollInterval); }, render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList data={this.state.data} /> <CommentForm onCommentSubmit={this.handleCommentSubmit} /> </div> ); } });ختامًاانتهيتَ لتوك من إنشاء مربع تعليقات في بضع خطوات بسيطة. يُمكنك الآن التَّعرُّف على المزيد حول أسباب استخدام React، أو الخوض في مراجع API وبدء العمل. ترجمة -وبتصرّف- للمقال: Tutorial | React.