في جزء اليوم من ترجمة البرنامج التعليمي React ، سنتحدث عن خصائص المكون. هذا واحد من أهم المفاهيم التي تنعكس في هذه المكتبة.

→
الجزء 1: نظرة عامة على الدورة ، وأسباب شعبية React ، ReactDOM و JSX→
الجزء 2: المكونات الوظيفية→
الجزء 3: ملفات المكونات ، هيكل المشروع→
الجزء 4: مكونات الوالدين والطفل→
الجزء 5: بدء العمل في تطبيق TODO ، أساسيات التصميم→
الجزء 6: حول بعض ميزات الدورة ، JSX وجافا سكريبت→
الجزء 7: الأنماط المضمنة→
الجزء 8: مواصلة العمل على تطبيق TODO ، الإلمام بخصائص المكونات→
الجزء 9: خصائص المكون→
الجزء 10: ورشة عمل حول العمل مع خصائص المكون والتصميم→
الجزء 11: توليد العلامات الديناميكية وطريقة صفائف الخريطة→
الجزء 12: ورشة العمل ، المرحلة الثالثة من العمل على طلب TODO→
الجزء 13: المكونات القائمة على الفصل→
الجزء 14: ورشة عمل حول المكونات القائمة على الفصل ، وحالة المكون→
الجزء 15: ورش العمل الصحية المكونة→
الجزء 16: المرحلة الرابعة من العمل على طلب TODO ، التعامل مع الأحداث→
الجزء 17: المرحلة الخامسة من العمل على تطبيق TODO ، وتعديل حالة المكونات→
الجزء 18: المرحلة السادسة من العمل على طلب TODO→
الجزء 19: طرق دورة حياة المكونالجزء 20: الدرس الأول في التقديم الشرطي→
الجزء 21: الدرس الثاني وورشة العمل حول التقديم الشرطي→
الجزء 22: المرحلة السابعة من العمل على تطبيق TODO ، وتنزيل البيانات من مصادر خارجية→
الجزء 23: الدرس الأول حول العمل مع النماذج→
الجزء 24: نماذج الدرس الثاني→
الجزء 25: ورشة عمل حول العمل مع النماذج→
الجزء 26: بنية التطبيق ، نمط الحاوية / المكون→
الجزء 27: مشروع المقررالدرس 19. خصائص المكون في التفاعل
→
الأصلقم بإنشاء مشروع جديد باستخدام تطبيق
create-react-app
وتغيير شفرة العديد من الملفات القياسية من مجلد
src
.
فيما يلي رمز ملف
index.js
:
import React from "react" import ReactDOM from "react-dom" import "./index.css" import App from "./App" ReactDOM.render(<App />, document.getElementById("root"))
فيما يلي الأنماط الموضحة في ملف
index.css
:
body { margin: 0; } .contacts { display: flex; flex-wrap: wrap; } .contact-card { flex-basis: 250px; margin: 20px; } .contact-card > img { width: 100%; height: auto; } .contact-card > h3 { text-align: center; } .contact-card > p { font-size: 12px; }
إليك الرمز الموجود في ملف
App.js
:
import React from "react" function App() { return ( <div className="contacts"> <div className="contact-card"> <img align="center" src="http://placekitten.com/300/200"/> <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3> <p>Phone: (212) 555-1234</p> <p>Email: mr.whiskaz@catnap.meow</p> </div> <div className="contact-card"> <img align="center" src="http://placekitten.com/400/200"/> <h3><font color="#3AC1EF">▍Fluffykins</font></h3> <p>Phone: (212) 555-2345</p> <p>Email: fluff@me.com</p> </div> <div className="contact-card"> <img align="center" src="http://placekitten.com/400/300"/> <h3><font color="#3AC1EF">▍Destroyer</font></h3> <p>Phone: (212) 555-3456</p> <p>Email: ofworlds@yahoo.com</p> </div> <div className="contact-card"> <img align="center" src="http://placekitten.com/200/100"/> <h3><font color="#3AC1EF">▍Felix</font></h3> <p>Phone: (212) 555-4567</p> <p>Email: thecat@hotmail.com</p> </div> </div> ) } export default App
إليك الشكل الذي سيبدو عليه هذا التطبيق في المتصفح.
صفحة التطبيق في المتصفحبعد تحليل الكود ومظهر التطبيق ، يمكننا أن نستنتج أنه سيكون من الجيد استخدام مكونات خاصة لعرض البطاقات مع معلومات عن الحيوانات. الآن يتم تشكيل هذه العناصر عن طريق مكون
App
. النظر في ما تحدثنا عنه في الفصول السابقة ، يمكنك الذهاب أبعد من ذلك - التفكير في مكون عالمي يمكن تخصيصه عن طريق تمرير سمات أو خصائص إليه.
في تطبيقنا هناك بطاقات مع صور القطط ، وأسمائهم ومعلومات الاتصال لأصحابها (أو ربما أنفسهم) - هاتف وعنوان بريد إلكتروني. لإنشاء مكون سيصبح لاحقًا أساسًا لجميع هذه البطاقات ، يمكنك أن تأخذ أحد أجزاء العلامات التي أرجعها مكون
App
. على سبيل المثال - هذا:
<div className="contact-card"> <img align="center" src="http://placekitten.com/300/200"/> <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3> <p>Phone: (212) 555-1234</p> <p>Email: mr.whiskaz@catnap.meow</p> </div>
يعرض التطبيق أربع كتل من هذا القبيل ، يمكن استخدام كل منها لإنشاء مكون مستقل ، لكن هذا النهج لا يناسبنا. لذلك ، سنقوم بإنشاء مكون واحد سيصبح أساس جميع البطاقات المعروضة بواسطة التطبيق. للقيام بذلك ، قم بإنشاء ملف مكون جديد في مجلد
src
-
ContactCard.js
ثم ضع فيه رمزًا يُرجع العنصر
<div>
الأول الذي تم إرجاعه بواسطة مكون
App
، والذي تم ذكر رمزه أعلاه. فيما يلي رمز مكون
ContactCard
:
import React from "react" function ContactCard() { return ( <div className="contact-card"> <img align="center" src="http://placekitten.com/300/200"/> <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3> <p>Phone: (212) 555-1234</p> <p>Email: mr.whiskaz@catnap.meow</p> </div> ) } export default ContactCard
من الواضح أنك إذا قمت بإنشاء عدة مثيلات لهذا المكون ، فستحتوي جميعها على نفس البيانات ، لأن هذه البيانات مشفرة في كود المكون. ونود ، عند إنشاء مثيلات مختلفة لهذا المكون ، سيكون من الممكن تخصيص البيانات المعروضة به. النقطة المهمة هي أنه يمكن تمرير المكون بعض الخصائص ، والتي يمكن استخدامها بعد ذلك.
نحن نعمل مع المكونات الوظيفية ، والتي هي وظائف JS عادية ، والتي ، بفضل استخدام مكتبة React ، يمكن استخدام إنشاءات خاصة. كما تعلمون ، يمكن أن تأخذ الدالات وسيطات ، على الرغم من إمكانية استخدامها بدون وسائط. يمكن أن يكون
ContactCard
لمكون
ContactCard
بنا ، بالشكل الذي يوجد به الآن ، وظيفة بسيطة بحيث تقوم ، دون قبول أي شيء ، ببساطة بإرجاع مجموع رقمين:
function addNumbers() { return 1 + 1 }
يمكن استخدامه لمعرفة مجموع الأرقام 1 و 1 ، ولكن ، على سبيل المثال ، لإضافة 1 و 2 ، باستخدام وظائف لا تقبل أي إدخال ، يجب أن نكتب وظيفة جديدة. من الواضح تمامًا أن هذا النهج سيؤدي إلى إزعاج كبير إذا كنت بحاجة إلى إضافة أرقام مختلفة ، لذلك في مثل هذه الحالة ، سيكون من الحكمة إنشاء وظيفة عالمية لإضافة أرقام ، تأخذ رقمين وتُرجع مجموعهما:
function addNumbers(a, b) { return a + b }
تعتمد وظيفة هذه الوظيفة على الوسائط التي تم تمريرها إليها عند استدعائها. من خلال إنشاء مكونات React ، يمكننا أن نذهب بنفس الطريقة تمامًا.
نحن نستورد مكون
App.js
ContactCard
أربعة من
ContactCard
، دون حذف الكود الذي يشكل البطاقات في صفحة التطبيق الآن:
import React from "react" import ContactCard from "./ContactCard" function App() { return ( <div className="contacts"> <ContactCard /> <ContactCard /> <ContactCard /> <ContactCard /> <div className="contact-card"> <img align="center" src="http://placekitten.com/300/200"/> <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3> <p>Phone: (212) 555-1234</p> <p>Email: mr.whiskaz@catnap.meow</p> </div> <div className="contact-card"> <img align="center" src="http://placekitten.com/400/200"/> <h3><font color="#3AC1EF">▍Fluffykins</font></h3> <p>Phone: (212) 555-2345</p> <p>Email: fluff@me.com</p> </div> <div className="contact-card"> <img align="center" src="http://placekitten.com/400/300"/> <h3><font color="#3AC1EF">▍Destroyer</font></h3> <p>Phone: (212) 555-3456</p> <p>Email: ofworlds@yahoo.com</p> </div> <div className="contact-card"> <img align="center" src="http://placekitten.com/200/100"/> <h3><font color="#3AC1EF">▍Felix</font></h3> <p>Phone: (212) 555-4567</p> <p>Email: thecat@hotmail.com</p> </div> </div> ) } export default App
الآن ، دعونا نعمل على الكود المستخدم في إنشاء مكون
ContactCard
. من خلال إنشاء عناصر HTML منتظمة ، يمكننا تخصيص سماتها التي تؤثر على سلوكها ومظهرها. يتم ترميز أسماء هذه السمات حسب المعيار. في حالة المكونات ، يمكنك استخدام الطريقة نفسها تمامًا ، مع وجود الفرق الوحيد في أننا نتوصل إلى أسماء السمات أنفسنا ، ونقرر بأنفسنا كيفية استخدامها في رمز المكون.
تحتوي كل بطاقة على أربعة أجزاء من المعلومات ، والتي ، من بطاقة إلى أخرى ، يمكن أن تتغير. هذه صورة لقطة واسمها ، بالإضافة إلى هاتف وعنوان بريد إلكتروني. دع اسم القط موجودًا في خاصية
name
وعنوان الصورة في خاصية
imgURL
والهاتف في خاصية
phone
وعنوان البريد الإلكتروني في خاصية
email
.
لقد قمنا بتعيين هذه الخصائص على مثيلات مكونات
ContactCard
، وبما أننا نقوم بنقل البيانات من الكود الموجود بالفعل في
App
، سنقوم بحذف الأجزاء المقابلة لها. نتيجة لذلك ، سيبدو رمز مكون
App
كما يلي:
import React from "react" import ContactCard from "./ContactCard" function App() { return ( <div className="contacts"> <ContactCard name="Mr. Whiskerson" imgUrl="http://placekitten.com/300/200" phone="(212) 555-1234" email="mr.whiskaz@catnap.meow" /> <ContactCard name="Fluffykins" imgUrl="http://placekitten.com/400/200" phone="(212) 555-2345" email="fluff@me.com" /> <ContactCard name="Destroyer" imgUrl="http://placekitten.com/400/300" phone="(212) 555-3456" email="ofworlds@yahoo.com" /> <ContactCard name="Felix" imgUrl="http://placekitten.com/200/100" phone="(212) 555-4567" email="thecat@hotmail.com" /> </div> ) } export default App
صحيح أن مجرد نقل الخصائص إلى مكون لا يكفي لاستخدامها فيه. ستحتوي الصفحة ، التي سيتم تشكيلها بواسطة مكون
App
أعلاه ، على أربع بطاقات متطابقة ، يتم تعيين بياناتها في رمز مكون
ContactCard
، الذي لا يعرف حتى الآن ما يجب القيام به بالخصائص المنقولة إليه.
بيانات البطاقة مضغوطة في الرمز ؛ لا يمكن للمكون العمل مع الخصائص التي تم تمريرها إليهالذا حان الوقت للتحدث عن كيفية عمل مكون
ContactCard
مع الخصائص التي يتم تمريرها إليه عند إنشاء مثيل له.
ننتقل إلى حل هذه المشكلة من خلال الإشارة ، عند الإعلان عن وظيفة
ContactCard
، إلى أنها تقبل معلمة
props
. في هذه الحالة ، سيبدو رمز المكون كما يلي:
import React from "react" function ContactCard(props) { return ( <div className="contact-card"> <img align="center" src="http://placekitten.com/300/200"/> <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3> <p>Phone: (212) 555-1234</p> <p>Email: mr.whiskaz@catnap.meow</p> </div> ) } export default ContactCard
في الواقع ، يمكن تسمية هذه المعلمة بأي شيء تريده ، ولكن في React ، من المعتاد أن نسميها
props
، وغالبًا ما تسمى الخصائص التي نتحدث عنها هنا ببساطة "props".
المعلمة
props
هو كائن. خصائص هذا الكائن هي الخصائص التي يتم تمريرها إلى المكون عندما يتم إنشاء مثيل له. هذا ، على سبيل المثال ، في كائن
props
بنا سيكون
props
اسم خاصية
props.name
يحتوي على اسم القط الذي تم تمريره إلى المكون عندما تم إنشاء مثيل له. بالإضافة إلى ذلك ، سيكون لها خصائص
props.imgUrl
،
props.phone
،
props.email
. للتحقق من ذلك ، أضف الأمر
console.log(props)
في بداية وظيفة
ContactCard
.
import React from "react" function ContactCard(props) { console.log(props) return ( <div className="contact-card"> <img align="center" src="http://placekitten.com/300/200"/> <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3> <p>Phone: (212) 555-1234</p> <p>Email: mr.whiskaz@catnap.meow</p> </div> ) } export default ContactCard
سيؤدي هذا إلى إحضار كائن
props
تلقاه المكون إلى وحدة التحكم.
وجوه الدعائم وحدةهنا يمكنك رؤية إخراج أربعة كائنات من
ContactCard.js
. يوجد الكثير منهم لأننا نقوم بإنشاء أربعة مثيلات لمكون
ContactCard
.
كل هذا يعطينا فرصة لاستخدام في رمز المكون ، بدلاً من القيم المرمزة ، ما تم تمريره إليه عند إنشاء مثيله ، المتاح في شكل
props
كائن
props
.
ماذا لو حاولنا استخدام خاصية
props.imgUrl
هذا:
<img align="center" src=props.imgUrl/>
للوهلة الأولى ، قد تعمل مثل هذه الإنشاءات ، ولكن تذكر أننا نحتاج هنا إلى استخدام كيان من JavaScript في كود JSX. تحدثنا عن كيفية القيام بذلك في واحدة من الفصول السابقة. وهي ، في حالتنا ، يجب إرفاق خاصية الكائن بأقواس:
<img align="center" src={props.imgUrl}/>
نقوم بمعالجة العناصر الأخرى التي يتم إرجاعها بواسطة المكون بنفس الطريقة ، وبعد ذلك يأخذ الكود الخاص به بالشكل التالي:
import React from "react" function ContactCard(props) { return ( <div className="contact-card"> <img align="center" src={props.imgUrl}/> <h3><font color="#3AC1EF">▍{props.name}</font></h3> <p>Phone: {props.phone}</p> <p>Email: {props.email}</p> </div> ) } export default ContactCard
يرجى ملاحظة أنه في الحقول الخاصة بعرض الهاتف وعنوان البريد الإلكتروني ، تركنا النصوص
Phone:
Email:
مع وجود مسافات تتبعها ، حيث يتم استخدام هذه النصوص في جميع المكونات. إذا نظرت الآن إلى صفحة التطبيق ، ستلاحظ أنها تحتوي على أربع بطاقات مختلفة.
تشكلت الصفحة باستخدام مكون عالمييقبل مكوننا أربعة خصائص فقط. ماذا لو كان المكون يحتاج إلى تمرير ، على سبيل المثال ، 50 خاصية؟ ربما يكون تمرير كل خاصية مثل سطر منفصل ، كما هو الحال في مكون
App
، غير مريح. في مثل هذه الحالات ، يمكنك استخدام طريقة أخرى لنقل الخصائص إلى المكونات. يتكون ذلك في حقيقة أنه عند تكوين نسخة من المكون ، لا يتم نقله بقائمة الخصائص ، ولكن في عنصر ذو خصائص. إليك كيف يمكن أن تبدو على مثال المكون الأول:
import React from "react" import ContactCard from "./ContactCard" function App() { return ( <div className="contacts"> <ContactCard contact={{ name: "Mr. Whiskerson", imgUrl: "http://placekitten.com/300/200", phone: "(212) 555-1234", email: "mr.whiskaz@catnap.meow" }} /> <ContactCard name="Fluffykins" imgUrl="http://placekitten.com/400/200" phone="(212) 555-2345" email="fluff@me.com" /> <ContactCard name="Destroyer" imgUrl="http://placekitten.com/400/300" phone="(212) 555-3456" email="ofworlds@yahoo.com" /> <ContactCard name="Felix" imgUrl="http://placekitten.com/200/100" phone="(212) 555-4567" email="thecat@hotmail.com" /> </div> ) } export default App
هذا لا يعني أن هذا الأسلوب قلل إلى حد كبير مقدار الشفرة المستخدمة لوصف مثيل المكون. الحقيقة هي أن الخصائص التي تم تمريرها إلى المكون لا تزال مشفرة في التعليمات البرمجية ، على الرغم من أننا نقوم بتمرير مكون واحد فقط إلى المكون. يمكن الشعور بمزايا هذا النهج في المواقف التي يتم فيها الحصول على بيانات المكون من بعض المصادر الخارجية. على سبيل المثال ، من ملف JSON.
أثناء تعديل رمز مكون
App
المستخدم لإنشاء المثيل الأول لمكون
ContactCard
، تعطلت العملية الصحيحة للتطبيق. هكذا تبدو صفحته الآن.
عطل التطبيقكيف يمكن إصلاح هذا؟ لفهم ذلك ، سيكون من المفيد تحليل ما يحدث باستخدام الأمر
console.log(props)
.
تحليل الكائن الدعائمكما ترون ، يختلف كائن
props
الخاص بالمكون الأول عن الكائن نفسه للمكونين الثاني والتالي.
في مكون
ContactCard
نستخدم كائن
props
بناءً على افتراض أنه يحتوي على
name
،
imgUrl
وغيرها من الخصائص. هنا ، يتلقى المكون الأول خاصية واحدة فقط -
contact
. هذا يؤدي إلى حقيقة أن كائن
props
لديه خاصية واحدة فقط -
contact
، وهو الكائن ، ورمز المكون لا يوفر العمل مع مثل هذه البنية.
تحويل المكون الخاص بنا إلى نموذج استخدام خاصية واحدة فقط لكائن
contact
يحتوي على خصائص أخرى أمر بسيط للغاية. للقيام بذلك ، على سبيل المثال ، للوصول إلى خاصية
name
، يكفي استخدام بنية النموذج
props.contact.name
في رمز المكون. تصاميم مماثلة تسمح لنا بالعمل بشكل صحيح مع الخصائص الأخرى التي نحتاجها.
دعنا نعيد تدوير رمز المكون ، مع الأخذ في الاعتبار نقل
contact
كائن-كائن واحدة تحتوي على خصائص أخرى:
import React from "react" function ContactCard(props) { console.log(props) return ( <div className="contact-card"> <img align="center" src={props.contact.imgUrl}/> <h3><font color="#3AC1EF">▍{props.contact.name}</font></h3> <p>Phone: {props.contact.phone}</p> <p>Email: {props.contact.email}</p> </div> ) } export default ContactCard
يجب الآن عرض المكون الأول بشكل طبيعي ، لكننا لن نرى هذا في هذه المرحلة من المشروع ، حيث سيقوم النظام بإبلاغنا بالكثير من الأخطاء المتعلقة بحقيقة أن العديد من مثيلات مكون
ContactCard
تم إنشاؤها في مكون
App
لا تتلقى خاصية - كائن
contact
. عند تنفيذ الكود ، ستكون هذه الخاصية
undefined
. نتيجة لذلك ، جرت محاولة للإشارة إلى خاصية معينة ذات قيمة
undefined
، مما يؤدي إلى حدوث خطأ. سنقوم بإصلاح هذا من خلال معالجة رمز مكون
App
المسؤول عن تكوين مكونات
ContactCard
:
import React from "react" import ContactCard from "./ContactCard" function App() { return ( <div className="contacts"> <ContactCard contact={{ name: "Mr. Whiskerson", imgUrl: "http://placekitten.com/300/200", phone: "(212) 555-1234", email: "mr.whiskaz@catnap.meow" }} /> <ContactCard contact={{ name: "Fluffykins", imgUrl: "http://placekitten.com/400/200", phone: "(212) 555-2345", email: "fluff@me.com" }} /> <ContactCard contact={{ name: "Destroyer", imgUrl: "http://placekitten.com/400/300", phone: "(212) 555-3456", email: "ofworlds@yahoo.com" }} /> <ContactCard contact={{ name: "Felix", imgUrl: "http://placekitten.com/200/100", phone: "(212) 555-4567", email: "thecat@hotmail.com" }} /> </div> ) } export default App
الآن ستظهر صفحة التطبيق كما كانت من قبل.
كالمعتاد ، يوصى بتجربة المفاهيم التي تعلمتها اليوم من أجل فهمها بشكل أفضل. على سبيل المثال ، يمكنك العمل مع الكود وإضافة خصائص جديدة يتم تمريرها إلى المكون ومحاولة استخدامها في المكون.
ملخص
اليوم قدمنا مفهوم الخصائص التي يمكن نقلها إلى مكونات React من أجل التحكم في سلوكها ومظهرها. تشبه هذه الخصائص سمات عناصر HTML ، ولكن باستخدام الخصائص في المكونات ، يقرر المبرمج بشكل مستقل ما معنى هذه العناصر وماذا تفعل بالضبط بها في المكون. في المرة القادمة سيكون لديك درس عملي في العمل مع خصائص المكون والتصميم.
أعزائي القراء! كيف جربت الكود الخاص بمثال اليوم من أجل فهم خصائص مكونات React بشكل أفضل؟