لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 09/10/20 في كل الموقع
-
السلام عليكم ورحمة الله، مرحبا شباب، لدي استشكال في فهم هذه المعادلة قليلا، لقد وجدتها في احدى التحديات على موقع هرموش الستشكال هنا: for (int i = 1; i <= n; i++) { for (int k = 1; k <= n - i; k++) { System.out.print(" "); } System.out.print("*"); for (int j = 1; j < (i * 2) - 1; j++) { System.out.print("*"); } System.out.println(); } وخاصة for (int j = 1; j < (i * 2) - 1; j++) { System.out.print("*"); } وشكرا لكم1 نقطة
-
وعليكم السلام، أهلا بك، الكود يستخدم لطباعة شكل هرمي باستخدام الرمز * كالآتي: لديك ثلاثة حلقات for تستخدم لطباعة الشكل بالترتيب التالي: الحلقة الأولى الأساسية: for (int i = 1; i <= n; i++) وهي تقوم بتكرار مابداخلها عدد n مرة وتستخدم لطباعة طوابق الشكل الهرمي اعتماداً على قيمة n (عدد الطوابق). الحلقة الثانية: for (int k = 1; k <= n - i; k++){ System.out.print(" "); } وتستخدم لعمل المسافات في البداية قبل طباعة النجوم المستخدمة لعمل الشكل الهرمي، ويلاحظ أنها تتكرر n - i مرة، أي تتم طباعة المسافات اعتماداً على قيمة i (تعداد الطابق الهرمي) بحيث تتم طباعة المسافات بشكل متناقص كل مرة عند طباعة طابق هرمي جديد من الأعلى للأسفل. الحلقة الثالثة: System.out.print("*"); for (int j = 1; j < (i * 2) - 1; j++) { System.out.print("*"); } بعد إكمال طباعة المسافات، تتم طباعة نجم وحيد أولاً ومن ثم طباعة عدد زوجي من النجوم كل مرة ابتداءً بعدد 2 من النجوم في الطابق الثاني (أسفل العلوي) ومن ثم بشكل متزايد 4، 6، 8 لدى كل طابق جديد. ويمكن كذلك تبسيط الحلقة الثالثة بالشكل التالي: for (int j = 1; j < (i * 2); j++) { System.out.print("*"); } بحيث يتم الاستغناء عن طباعة النجم المنفرد في البداية ومن ثم طباعة عدد فردي من النجوم في كل طابق بعدد نجم وحيد في الطابق العلوي ومن ثم 3، 5، 7 في الطوابق اللاحقة وهكذا. وأخيراً بعد إكمال طباعة النجوم يتم عمل سطر جديد في نهاية الحلقة للطابق الجديد في الهرم باستخدام السطر: System.out.println();1 نقطة
-
مرحبَا أبوتركي.. هذا تنسيق (layout) بسيط جدًا قمت بتنفيذه الأن لعمل صفحة بنفس التنسيق الذي ترغبه : <body> <div class="row"> <!-- عمود المحتوى --> <div class="col-9"> <!-- الناف بار --> <div class="row"> </div> <!-- المحتوى الرئيسي --> <div class="row"> </div> <!-- الفوتر --> <div class="row"> </div> </div> <!-- عمود القائمة الجانبية --> <div class="col-3"> </div> </div> </body> طبعًا أنت بحاجة إلى إضافة محتوى حتى يظهر لك كيفية إصطفاف العناصر بعد ذلك بإمكانك إضافة التنسيقات المطلوبة للوصول إلى النتيجة التي ترغبها. الصفحة تتكون من صف رئيسي مقسم إلى عمودين العمود الأول على يسار الشاشة سيأخد مساحة 9 أعمدة من أصل 12 عمود أما العمود التاني سيظهر على يمين الشاشة و سيأخد مساحة 3 أعمدة ( المتبقية ). داخل العمود الأيسر قمنا بتقسيمه إلى 3 صفوف : الصف الأول للناف بار , الصف التاني للمحتوى , الصف الثالث للفوتر. أما العمود الأيمن بإمكانك وضع داخلة محتويات السايد بار.1 نقطة
-
مرحبًا.. موسوعة حسوب هي عبارة عن توثيق لبعض اللغات البرمجية و المكتبات الشهيرة و المفاهيم المتعقلة بمجال البرمجة مثل الخوارزميات و الأنماط , و التوثيق هو ليس لشرح اللغة و التعمق فيها بل هو أشبه بمرجع تجد فيه كل ما يتعلق باللغة على شكل نقاط و أقسام مرتبة كل نقطة يتم إعطاء نبدة تعريفية عنها فقط و ليس شرحًا مفصلًا. بالنسبة للخوارزميات فهي لا ترتبط بلغة برمجية معينة , كذلك في التوثيق مذكور كل ما هو متعلق بالخوارزميات مع إعطاء نبذة تعريفية ورابط للموضوع على الويكيبيديا في حال كان القارئ يرغب في معرفة المزيد. لماذا لا يوجد توثيق للغة الجافا؟ الموسوعة في تطوير و تحسين مستمر سوى بإضافة توثيق للغات جديدة أو تحسين التوثيقات السابقة , قد يتم إضافتها في المستقبل القريب , بإمكانك إرسال طلبك لإدارة الموسوعة. إذا أردت التعمق أكثر في الخوارزميات أنصحك بالبحث عن مقالات و كتب و ليس توثيقًا و لا تنسى بأن الخوارزميات مادة دسمة جدًا و التعمق فيها يحتاج بعض المعرفة بمادة الرياضيات و هي مادة تدرس في الجامعات.1 نقطة
-
و عليكم السلام أهلاً بك . لنفترض أنك قمت بإنشاء عملية التسجيل بالشكل الصحيح و بدون أخطاء . الآن عملية التأكد من الإيميل الخاص بالمستخدم . $to = $email; // إرسال الإيميل الى المستخدم $subject = 'Signup | Verification'; // عنوان الإيميل $message = ' Thanks for signing up! Your account has been created, you can login with the following credentials after you have activated your account by pressing the url below. ------------------------ Username: '.$name.' Password: '.$password.' ------------------------ Please click this link to activate your account: http://www.yourwebsite.com/verify.php?email='.$email.'&hash='.$hash.' '; // الرسالة التي سوف تصل المستخدم $headers = 'From:noreply@yourwebsite.com' . "\r\n"; // عنوان المرسل mail($to, $subject, $message, $headers); // دالة الإرسال و هذه عبارة عن رسالة بريد إلكتروني تصل المستخدم و تحتوي على رابط فور النقر عليه سيتم تفعيل البريد . .. <?php if(!empty($_GET['code']) && isset($_GET['code'])) { $code=$_GET['code']; $sql=mysqli_query($con,"SELECT * FROM userregistration WHERE activationcode='$code'"); $num=mysqli_fetch_array($sql); if($num>0) { $st=0; $result =mysqli_query($con,"SELECT id FROM userregistration WHERE activationcode='$code' and status='$st'"); $result4=mysqli_fetch_array($result); if($result4>0) { $st=1; $result1=mysqli_query($con,"UPDATE userregistration SET status='$st' WHERE activationcode='$code'"); $msg="Your account is activated"; } else { $msg ="Your account is already active, no need to activate again"; } } else { $msg ="Wrong activation code."; } } ?> و هنا الطريقة الثانية و هي طريقة وصول كود الى المستخدم و عليه أن يدخله في الموقع لكي يتم تفعيل الحساب . ملاحظة - هذه الأكواد لن تعمل معك بالشكل الصحيح بمجرد النسخ و اللصق قم بالتعديل على الأكواد بما يتناسب مع المشروع الخاص بك . مقالات مفيدة تحتوي على أمثلة مبسطة . الطريقة الأولى - المقال الطريقة الثانية - المقال شكراً لك1 نقطة
-
يمكنك القيام بذلك بتخزين البيانات التي يقوم بإدخالها المستخدم عند تسجيل الدخول "بعد التحقق من صحتها طبعًا" في قاعدة بيانات و بعدها يمكنك إرسال رسالة تأكيد إلى الإيميل الذي قام بتسجيل الدخول "فهو مخزن الان في قاعدة البيانات" باستخدام دالة mail الخاصة ب php. يمكنك قراءة هذا المقال فهو يشرح كيفية بناء script لتأكيد التسجيل من الصفر. في هذا المقال يتم إرسال رسالة تحتوي على اسم مستخدم و كلمة مرور للمستخدم . يمكنك الإطلاع على هذا المقال أيضًا فهو يشرح كيفية التحقق من التسجيل عبر إرسال رابط إلى إيميل المستخدم و يتم التأكيد بعد أن يضغط المستخدم على الرابط.1 نقطة
-
عندي مشكله في تعلم البرمجه وشعرت بالاحباط بعد اشتراكي بالدوره انه يجتاج وقت وجهد ليي بالقليل وماذا نصيحتكم لي وماذا افعل هل يوجد شي اخرى ام ستمر لأنى احترت ؟1 نقطة
-
مرحباً @Bjm678 لنكن صريحين مع بعض البرمجة ليست الدخول في دورة و إتمامها و فقط مبروك عليك أصبحت مبرمج محترف . أو مثلا تقول سأضع مدة شهر أو شهرين أو حتى سنة و تقول بعد مرور هذه المدة في التعلم أصبحت مبرمج محترف. طالما اخترت هذا المجال عليك أن تحبه فإذا لم تحب هذا المجال فما الداعي. حتى تصبح مبرمج محترف يجب أن تحب البرمجة أولاً و يجب أن تتوفر لديك الرغبة في التعلم و معرفة كيف تم عمل الأشياء التي تراها حولك ثانياً. أدري أن الأمر صعب في البداية. ستفشل أحياناً ستمر بمراحل ملل و ستصل لمرحلة تقرر فيها التوقف لكن إن كنت تحب البرمجة أنصحك بالإستمرار و الصبر. و كي لا تسقط في الملل أنصحك بوضع خطة للتعلم ضع وقت محدد للدراسة فالعقل البشري محدود في النهاية وإذا أكثرت عليه سيحبطك و سيمل و يعطيك أسباب واهية أنه عليك التوقف و يزينها لك. أَحطْ نفسك بِطاقات إيجابية و ابتعد عن الأشخاص السلبيين فهذا يؤثر عليك. أي دورة موجودة على الإنترنت أو الواقع صُممت أن تُعلمك بعض المبادئ الأساسية في بعض التقنيات و تُلقنك بعض الخبرات و المهارات و ستفتح لك مجالات أخرى للتعلم و الإستمرار و التعمق أكثر . في مشاهدتك للدروس أنصحك بالفهم الجيد و عدم التسرع و إذا لم تصل للفهم أعد مشاهدة الدرس و أسأل حتى تترسخ لديك المفاهيم. لا تنتقل للدرس التالي قبل فهمك للدرس الحالي . لديك موسوعة حسوب توثيق لمعظم لغات البرمجة باللغة العربية إذا كان لديك لُبس في مصطلح أو مفهوم ما يمكنك البحث عنه فيها حتى يتضح لك المعنى. بالتوفيق.1 نقطة
-
بالطبع أنصحك بالاستمرا. فما تواجهه الآن أمر طبيعي و يحدث مع جميع المبتدئين فتعلم البرمجة و إتقانها ليس بالأمر السهل و يحتاج الكثير و الكثير من الوقت و المجهود و الصبر. فتعلم أي مهارة جديدة ليس بالأمر السهل و بالطبع لا أحد يستطيع أن يتقن أو يفهم مجالًا مثل مجال البرمجة في أيام قليلة فالأمر يحتاج إلى شهور من العمل و الممارسة حتى تتمكن من الفهم بشكل جيد. أنصحك بالاستمرار و عدم التسرع و مشاهدة الدروس أكثر من مرة و قراءة المقالات حتى تتمكن من الفهم بأكبر نسبة ممكنة و إن لم تتمكن من فهم بعض الأشياء لابأس يمكنك دائمًا أن تسأل عنها أو المحاولة معها لاحقًا. كما أنصحك بالممارسة و التدرب كثيرًا فهذا ما سيجعل منك مطور ماهر و سيجعلك تتمكن من الفهم بشكل أفضل. بالتوفيق.1 نقطة
-
مرحباً بك : أي مجال يحتاج إلى صبر وجهد ودراسة وعدم إستسلام وعزيمة ولذلك هناك فرق في الوظائف وفرق في المرتبات والحوافز للوظيفة ذاتها .. أما عن البرمجة فمن وجهة نظهري هي مجال ممتع للغاية لكن إذا كنت في البداية وفي أول الطريق ستشعر كثيراً بالملل والإحباط ولكن عليك عدم الإستسلام وإذا لم تفهم أي معلومة فيجب أن تعيد مشاهدة الدرس مرة أخرى حتي تفهم وتبحث عن المعلومة من أكثر من مصدر ولكن لا تحفظ الأكواد أبداً لأنك مع الوقت ستفهم ويكون تلقائياً لديك كتابة البرمجيات وسأرشح لك قناة ستأخذك من الصفر إلى أن يكون مستواك جيد جداً تذاكر منها بجانب الدورات التي لديك قناة الزيرو ويب سكول1 نقطة
-
مرحباً أبو تركي : البوتستراب يستخدم fluid ليستفيد من الصفحة كاملة أما بداخل ال fluid يستخدم ال grid system أو نظام الشبكة ( وهو نظام يقو بتقسيم ال container ل 12 عمود ) لتوزيع العناصر بالمساحات التي يرغبون بها فمثلاً ال sidebar يأخذ مساحة 3 أعمدة من ال fluid وباقي الصفحة تأخذ 9 أعمدة من ال fluid ... أرجو أن تدرس ال grid-system من هذا المثال وأعتقد هذا المثال مقارب لما تبحث عنه1 نقطة
-
التنسيق margin بالقيمة auto يجعل العنصر يظهر في منتصف الصفحة أفقيًا بجعل الحواف الخارجية تلقائية. div { margin: auto; } في المثال التالي لاحظ موضع ال div الذي له الإطار الأحمر بعد إضافة التنسيق margin:auto و بعد إزالته. في وجود التنسيق margin:auto بدون التنسيق margin:auto أما التنسيق div { margin-left:auto } يجعل العنصر يظهر في نهاية الصفحة أفقيًا "في أقصى اليمين" بجعل الحواف الخارجية من جهة اليسار تلقائية. يمكنك قراءة المزيد في هذه المقالات1 نقطة
-
مرحبًا @Shahad Mohammad, عندما نُحدد عرض العنص(width) عندها يمكنُنا ان نجعل العنصر في المنتصف بإستخدام : margin-left: auto; margin-right: auto; القيمة auto للهامش left و right تجعل العنصر يقوم بجعل كِلا الهوامش يحملان قيم متساوية مما يجعل العنصر يتموضع في النتصف . يمكنك تعلُم المزيد عن الهوامش من هنا .1 نقطة
-
مرحبًا.. الرجاء إرفاق مثال لعمل قمت به و توضيح المشكلة التي تواجهك للوصول إلى النتيجة المرغوبة , حتى يتسنى لنا مساعدتك في إنجازه.1 نقطة
-
أهلا بك. الجملة صائبة لأنه دائماً عند وراثة Class يتم إستدعاء الـ constructor الخاص بالكلاس الأب أولاً وبعدها يتم تنفيذ الـ constructor الخاص بالكلاس الوارث. وفي حالة وجود متغيرات parameters يتم تمريرها إلى constructor الكلاس الأب عندها لايمكن عمل constructor للكلاس الوراث بدون تمرير المتغيرات الخاصة بـ constructor الكلاس الأب أولاً. يمكنك الإطلاع على هذا المقال للتعرف أكثر على قواعد الوراثة داخل C++.1 نقطة
-
أهلا بك، سبب المشكلة عدم وجود صلاحيات لديك للكتابة على القرص، إذا كنت تقوم بتشغيل البرنامج من خلال CMD فقم بمحاولة تشغيله كـ Administrator من خلال النقر على الزر الأيمن ومن ثم Run as administrator ويفترض أن تحل المشكلة لديك.1 نقطة
-
سنتحدث في هذا المقال عن كيفية ضبط صفحة HTML لكي يمكن تفسيرها في متصفح الويب، وسيتمكن المتصفح في وقت التنفيذ من تحويل تعابير JSX ويشغِّل شيفرة React بنجاح. استخدام react.js و react-dom.js في صفحة HTML الملف react.js هو الملف الأساسي الذي نحتاج له لإنشاء عناصر React وكتابة مكونات React. عندما ترغب بعرض المكونات التي أنشأتها في مستند HTML (أي كتابتها إلى DOM) فستحتاج أيضًا إلى الملف react-dom.js. يعتمد الملف react-dom.js على الملف react.js ويجب تضمينه بعد تضمين الملف react.js. مثالٌ عن مستند HTML يحتوي على React: <!DOCTYPE html> <html> <head> <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script> </head> <body> </body> </html> بتحميل الملفين react.js و react-dom.js في صفحة HTML، أصبح بإمكاننا إنشاء عقد ومكونات React ثم عرضها في DOM. المثال البسيط الآتي يُنشِئ مكوِّن HelloMessage يحتوي على عقدة العنصر <div> ثم سيُعرَض في شجرة DOM داخل عنصر HTML المُعرَّف <div id="app"></div>: <!DOCTYPE html> <html> <head> <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script> <script src="https://unpkg.com/create-react-class@15.6.0-rc.0/create-react-class.js" crossorigin></script> </head> <body> <div id="app"></div> <script> var HelloMessage = createReactClass({ // استخدمنا هذه الوحدة لترى كيف تستعمل displayName: 'HelloMessage', render: function render() { return React.createElement('div',null,'Hello ',this.props.name); } }); ReactDOM.render(React.createElement(HelloMessage,{ name: 'Ahmed' }), document.getElementById('app')); </script> </body> </html> هذا كل ما تحتاج له لاستخدام React. لكنه لن يُمكِّنك من استخدام JSX، والتي سنناقشها في القسم التالي. ملاحظات لا تجعل العنصر <body> العنصر الأساسي في تطبيق React. احرص دومًا على وضع عنصر ؤ داخل <body>، وأعطه ID، ثم صيِّر (render) المكونات داخله. وهذا يعطي React مجالًا خاصًا بها لتجري التعديلات، دون أن تقلق عن أي شيءٍ آخر يجري تعديلات على العناصر الأبناء للعنصر <body>. استخدام JSX عبر Babel عملية إنشاء المكوِّن HelloMessage وعنصر <div> في المثال الآتي جرت باشتقاق الصنف React.Component واستخدام الدالة React.createElement(). يُفترَض أن تبدو الشيفرة الآتية مألوفةً لأنها مماثلة لشيفرة HTML من القسم السابق: <!DOCTYPE html> <html> <head> <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script> </head> <body> <div id="app"></div> <script> class HelloMessage extends React.Component { render(){ return React.createElement('div', null, 'Hello ', this.props.name); } }; ReactDOM.render(React.createElement(HelloMessage, { name: 'Ahmed' }), document.getElementById('app')); </script> </body> </html> يمكنك أن تستخدم JSX اختياريًا عبر Babel، فمن الممكن تبسيط عملية إنشاء عناصر React بتجريد استدعاءات الدالة React.createElement() ونكتبها بطريقة تشبه طريقة كتابة عناصر HTML. فبدلًا من كتابة الشيفرة الآتية التي تستخدم الدالة React.createElement(): return React.createElement('div', null, 'Hello ', this.props.name); يمكننا أن نكتب ما يلي باستخدام JSX: return <div>Hello {this.props.name}</div>; ثم باستخدام Babel نستطيع تحويلها إلى الشيفرة التي تستخدم React.createElement() لكي يتمكن محرِّك JavaScript من تفسيرها. يمكننا القول مجازًا أنَّ JSX هي شكلٌ من أشكال HTML التي تستطيع كتابتها مباشرةً ضمن شيفرة JavaScript والتي تحتاج إلى خطوة إضافية هي التحويل، وتجرى عملية التحويل باستخدام Babel إلى شيفرة ECMAScript 5 لكي تتمكن المتصفحات من تشغيلها. بعبارةٍ أخرى، سيحوِّل Babel شيفرة JSX إلى استدعاءات للدالة React.createElement(). سنتحدث عن المزيد من تفاصيل JSX في القسم المخصص لها، لكننا الآن يمكننا أن نعدّ JSX على أنها طبقة تجريد اختيارية توفَّر للسهولة عند إنشاء عناصر React، ولن تعمل في متصفحات ES5 ما لم نحوِّلها بدايةً باستخدام Babel. تحويل JSX عبر Babel في المتصفح يُضبَط عادةً Babel لكي يُعالِج ملفات JavaScript أثناء عملية التطوير باستخدام أداة سطر الأوامر الخاصة به (عبر استخدام Webpack على سبيل المثال)؛ لكن من الممكن استخدام Babel مباشرةً في المتصفح بتضمين سكربت معيّن. ولمّا كنّا في بداياتنا فسنتفادى استخدام الأدوات التي تعمل من سطر الأوامر أو نتعلم استخدام مُحمِّل للوحدات، وذلك لكي ننطلق في React. استخدام browser.js لتحويل JSX في المتصفح حوّلنا مكوِّن React في مستند HTML الآتي إلى صياغة JSX، وستحدث عملية التحويل بسبب تضيمننا لملف babel.min.js وإعطائنا لعنصر <script> الخاصية type مع القيمة text/``b``abel: <!DOCTYPE html> <html> <head> <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js" crossorigin></script> </head> <body> <div id="app"></div> <script type="text/babel"> class HelloMessage extends React.Component { // React.Component لاحظ استخدام render(){ return <div>Hello {this.props.name}</div>; } }; ReactDOM.render(<HelloMessage name="Ahmed" />, document.getElementById('app')); /*** سابقًا ***/ /* var HelloMessage = createReactClass({ * render: function() { * return <div>Hello {this.props.name}</div>; * } * }); * * ReactDOM.render(<HelloMessage name="Ahmed" />, document.getElementById('app')); */ </script> </body> </html> تحويلنا لشيفرة JSX في المتصفح هو حلٌ سهلٌ وبسيط، لكنه ليس مثاليًا لأنَّ عملية التحويل تجري في وقت التشغيل، وبالتالي استخدام babel.min.js ليس حلًا عمليًا يمكن استخدامه في البيئات الإنتاجية. ملاحظات أداة Babel هي اختيار المطورين من فريق React لتحويل شيفرات ES* وصيغة JSX إلى شيفرة ES5. تعلّم المزيد حول Babel بمراجعة توثيقه. باستخدام صيغة JSX: أصبح بإمكان الأشخاص غير المتخصصين تقنيًا فهم وتعديل الأجزاء المطلوبة. فيجد مطورو CSS والمصممون صيغة JSX أكثر ألفةً من شيفرة JavaScript. يمكنك استثمار كامل قدرات JavaScript في HTML وتتجنب تعلّم أو استخدام لغة خاصة بالقوالب. لكن اعلم أن JSX ليس محرّك قوالب، وإنما صيغة تصريحية للتعبير عن البنية الهيكلية الشجرية لمكونات UI. سيجد المُصرِّف (compiler) أخطاءً في شيفرة HTML الخاصة بك كنتَ ستغفل عنها. تحث صياغة JSX على فكر استخدام الأنماط السطرية (inline styles) وهو أمرٌ حسن. اعرف محدوديات JSX. تجري كتابة مواصفة JSX كمسودة لكي تُستخدَم من أي شخص كإضافة لصياغة ECMAScript. استخدام ES6 و ES* مع React Babel ليس جزءًا من React، وليس الغرض من إنشاء Babel هو تحويل JSX، وإنما أُنشِئ كمُصرِّف JavaScript (compiler) بادئ الأمر. إذ يأخذ شيفرة ES ويحوِّلها لكي تعمل على المتصفحات التي لا تدعم شيفرة ES. في هذه الآونة، يستخدم Babel أساسيًا لتحويل شيفرات ES6 و ES7 إلى ES5. عند إجراء عمليات التحويل هذه فمن البسيط تحويل تعابير JSX إلى استدعاءات React.createElement(). وبجانب تحويل Babel لشيفرات JSX، فيسمح أيضًا تحويل الشيفرات التي تعمل في إصدارات مستقبلية من ES*. مستند HTML الآتي يحتوي على مكوِّن HelloMessage مع إعادة كتابته لكي يستفيد من ميزة الأصناف في ES6. فلن يحوِّل Babel صيغة JSX فحسب، بل سيحوِّل صيغة أصناف ES6 إلى صيغةٍ تستطيع المتصفحات التي تحتوي محرِّك ES5 تفسيرها: <!DOCTYPE html> <html> <head> <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js" crossorigin></script> </head> <body> <div id="app"></div> <script type="text/babel"> class HelloMessage extends React.Component { // React.Component لاحظ استخدام render(){ return <div>Hello {this.props.name}</div>; } }; ReactDOM.render(<HelloMessage name="John" />, document.getElementById('app')); /*** سابقًا ***/ /* var HelloMessage = createReactClass({ * render: function() { * return <div>Hello {this.props.name}</div>; * } * }); * * ReactDOM.render(<HelloMessage name="John" />, document.getElementById('app')); */ </script> </body> </html> يأخذ Babel في المستند السابق الشيفرةَ الآتية: class HelloMessage extends React.Component { render(){ return <div>Hello {this.props.name}</div>; } }; ReactDOM.render(<HelloMessage name="John" />, document.getElementById('app')); ويحولها إلى: "use strict"; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var HelloMessage = (function (_React$Component) { _inherits(HelloMessage, _React$Component); function HelloMessage() { _classCallCheck(this, HelloMessage); _get(Object.getPrototypeOf(HelloMessage.prototype), "constructor", this).apply(this, arguments); } _createClass(HelloMessage, [{ key: "render", value: function render() { return React.createElement( "div", null, "Hello ", this.props.name ); } }]); return HelloMessage; })(React.Component); ; ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), document.getElementById('app')); أغلبية ميزات ES6 (مع بعض الاستثناءات الطفيفة) يمكن تحويلها باستخدام Babel. ملاحظات بالطبع ما يزال بإمكاننا استخدام Babel لغرضه الأساسي (وهو تصريف شيفرات JavaScript الحديثة إلى شيفرة JavaScript القديمة) دون استخدام JSX. لكن أغلبية المطورين الذين يستعملون Babel يستفيدون من قدرته على تحويل JSX إضافةً إلى ميزات ES* غير المدعومة في المتصفحات القديمة. يمكنك مراجعة توثيق Babel لمزيدٍ من المعلومات. تجربة React في JSFiddle يمكن استخدام نفس الضبط الذي أجريناه في هذا المقال مع JSFilddle. إذ تُستعمَل نفس الملفات (react.js و react-dom.js و babel.min.js) لجعل تنفيذ تطبيقات React سهلًا. هذا مثالٌ عن JSFiddle يحتوي على مكوِّن HelloMessage المستخدم في هذا المقال. لاحظ أنَّ لسان Babel يشير إلى أنَّ شيفرة JavaScript الموجودة في هذا اللسان ستحوَّل باستخدام Babel. وإذا ضغطتَ على لسان Resources ستجد أنَّ JSFiddle يُضمِّن الملفين react.js و react-dom.js. سيُفتَرَض بعد قراءتك لهذا المقال أنَّك تدرك ما هي المتطلبات الأساسية لإعداد React و Babel عبر babel.min.js، وصحيحٌ أنَّ JSFiddle لا يُصرِّح بوضوح عن طريقة إعداده، لكنه يستخدم نفس الضبط السابق (أو ما يشبهه) لتشغيل شيفرات React. ترجمة وبتصرف للفصل React Setup من كتاب React Enlightenment1 نقطة
-
React.js هي مكتبة JavaScript التي يمكن أن تستخدم لبناء واجهات المستخدم؛ فباستخدام React يمكن للمستخدمين إنشاء مكوِّنات قابلة لإعادة الاستخدام، وهذه المكونات تظهر البيانات أثناء تغيِّرها مع الزمن. يسمح لنا React Native بإنشاء تطبيقات أصيلة للهواتف الذكية باستخدام React. بكلمات أخرى، React هي أداة في JavaScript التي تُسهِّل إنشاء وصيانة واجهات المستخدم ذات الحالة (stateful) وعديمة الحالة (stateless)، وتوفر القدرة على تعريف وتقسيم واجهة المستخدم إلى مكوِّنات منفصلة (تسمى أيضًا بمكونات React) باستخدام عقد شبيهة بلغة HTML تسمى عقد React (أي React nodes). ستتحول عقد React في النهاية إلى صيغة قابلة للعرض في واجهات المستخدم (مثل HTML/DOM أو canvas أو SVG …إلخ.). يمكنني أن أستفيض بالشرح محاولًا تعريف React باستخدام الكلمات، لكنني أظن أنَّ من الأفضل أن أريك ما تفعله. لا تحاول أن تفهم كل التفاصيل الدقيقة أثناء شرحي لما بقي من هذا المقال، فالغرض من بقية هذه السلسلة أن تشرح لك بالتفصيل ما سيرد في هذه المقدمة. استخدام React لإنشاء مكونات شبيهة بعنصر select>> ما يلي هو عنصر <select> يحتوي على عناصر <option>. لحسن الحظ، الغرض من العنصر <select> معروفٌ لديك: <select size="4"> <option>Volvo</option> <option>Saab</option> <option selected>Mercedes</option> <option>Audi</option> </select> عندما يفسِّر المتصفح الشجرة السابقة من العناصر فسيُنتِج واجهة مستخدم تحتوي على قائمة نصية من العناصر التي يمكن اختيارها. أما في المتصفح، فشجرة DOM وشجرة DOM الظل (shadow DOM) تعملان معًا خلف الكواليس لتحويل العنصر <select> إلى مكوِّن UI. لاحظ أنَّ المكوِّن <select> يسمح للمستخدم باختيار أحد العناصر وبالتالي سيُخزِّن حالة ذاك الاختيار (أي انقر على Volvo وستختارها بدلًا من Mercedes). يمكننا باستخدام React إنشاء مكوِّن <select> خاص بنا باستخدام عقد React لإنشاء مكوِّن React والذي في النهاية سيُنتِج عناصر HTML في شجرة DOM. لنُنشِئ مكوِّنًا خاصًا بنا شبيهًا بالعنصر <select> باستخدام React. تعريف مكون React (أي React Component) سنُنشِئ فيما يلي مكوِّن React باشتقاق الصنف (class) React.Component لإنشاء المكوِّن MySelect. كما ترى، المكوِّن MySelect مُنشَأ من عدِّة أنماط إضافةً إلى عقدة <div> فارغة: class MySelect extends React.Component { // MySelect تعريف المكوِّن render(){ var mySelectStyle = { border: '1px solid #999', display: 'inline-block', padding: '5px' }; // JSX استخدام {} للإشارة إلى متغير جافاسكربت داخل // JSX باستخدام <div> سنعيد عنصر return <div style={mySelectStyle}></div>; } }; العنصر <div> السابق شبيهٌ بعناصر HTML العادية، وهو موجودٌ داخل شيفرة JavaScript التي تسمى JSX! صيغة JSX هي صياغة JavaScript اختيارية ومخصصة التي تستخدمها مكتبة React للتعبير عن عقد React التي يمكن أن ترتبط مع عناصر HTML حقيقية، أو عناصر مخصصة، أو عقد نصية. علينا ألّا نفترض أنَّ عقد React المُعرَّفة باستخدام JSX مماثلة تمامًا لعناصر HTML، فهنالك بعض الاختلافات بينها، وبعض القصور أيضًا. يجب تحويل صياغة JSX إلى شيفرات JavaScript حقيقية التي يمكن تفسيرها من محركات ECMAScript 5، فإن لم تحوّل الشيفرة السابقة فستسبب خطأً في JavaScript. الأداة الرسمية لتحويل شيفرات JSX إلى شيفرات JavaScript تسمى Babel. بعد أن يحوِّل Babel العنصر <div> في الشيفرة السابقة إلى شيفرة JavaScript فستبدو كما يلي: return React.createElement('div', { style: mySelectStyle }); بدلًا من: return <div style={mySelectStyle}></div>; في الوقت الحالي، ضع في ذهنك أنَّه عندما تكتب عناصر شبيهة بعناصر HTML في شيفرة React فستحوَّل في نهاية المطاف إلى شيفرة JavaScript حقيقية، إضافةً إلى تحويل أي شيفرة مكتوبة تحتوي على ميزات ECMAScript 6 وما بعدها إلى ECMAScript 5. المكوِّن <MySelect> يحتوي -عند هذه النقطة- على عقدة <div> فارغة فقط، أي أنَّ مكوِّن دون أي فائدة، لذا دعونا نغيِّر ذلك. سنُعرِّف مكونًا آخر باسم <MyOption> وسنستخدم المكوِّن <MyOption> داخل المكوِّن <MySelect> (ويسمى ذلك التركيب أي composition). تفحَّص شيفرة JavaScript المُحدَّثة الآتية التي تُعرِّف كلًا من مكونَي <MySelect> و <MyOption>: class MySelect extends React.Component { // MySelect تعريف المكوِّن render(){ var mySelectStyle = { border: '1px solid #999', display: 'inline-block', padding: '5px' }; // JSX استخدام {} للإشارة إلى متغير جافاسكربت داخل // <MyOption> يحتوي على المكون JSX باستخدام <div> إعادة عنصر return ( <div style={mySelectStyle}> <MyOption value="Volvo"></MyOption> <MyOption value="Saab"></MyOption> <MyOption value="Mercedes"></MyOption> <MyOption value="Audi"></MyOption> </div> ); } }; class MyOption extends React.Component { // MyOption تعريف المكون render(){ // JSX باستخدام <div> إعادة عنصر return <div>{this.props.value}</div>; } }; يفترض أنَّك لاحظت وجود المكوِّن <MyOption> داخل المكوِّن <MySelect> والذين أنشأناهما باستخدام JSX. تمرير خيارات المكون باستخدام خاصيات React لاحظ أنَّ المكوِّن <MyOption> يتألف من عنصر <div> يحتوي على التعبير {this.props.value}. تُستخدَم الأقواس المعقوفة {} داخل JSX للإشارة أنَّ محتواها هو تعبيرٌ صالحٌ في JavaScript. بعبارة أخرى، يمكننا أن نكتب شيفرات JavaScript عادية داخل القوسين {}. استخدمنا القوسين {} للوصول إلى الخاصيات المُمرَّرة إلى المكوِّن <MyOption>. بعبارةٍ أخرى، عندما يعرض المكوِّن <MyOption> فستوضع قيمة الخيار value التي جرى تمريرها عبر خاصيةٍ شبيهةٍ بخاصيات HTML (أي value="Volvo") داخل عنصر <div>. هذه الخاصيات التي تشبه خاصيات HTML تسمى خاصيات React، وتستخدمها مكتبة React لتمرير الخيارات التي لا تتغير إلى المكوِّنات، ومرَّرنا في مثالنا الخاصية value إلى المكوِّن <MyOption>، والأمر لا يختلف عن تمرير وسيط إلى دالة JavaScript، وهذا ما تفعله JSX خلف الكواليس. تصيير (Render) مكوِّن إلى شجرة DOM الافتراضية (Virtual DOM) ثم إلى شجرة DOM في هذه المرحلة، عرَّفنا مكوِّنين من مكونات React، لكننا لم نصيِّرها إلى شجرة DOM الافتراضية ومنها إلى شجرة HTML DOM. قبل أن نفعل ذلك، أود أن أشير إلى أنَّ كل ما فعلناه هو تعريف مكونين باستخدام JavaScript. وكل ما فعلناه -نظريًا- هو تعريف مكونات UI، وليس من الضروري أن تذهب هذه المكونات إلى شجرة DOM أو حتى إلى شجرة DOM الافتراضية (Virtual DOM). ويمكننا -نظريًا- أن نصيّر (render) هذه المكونات إلى منصة من منصات الهواتف الذكية أو إلى العنصر <canvas>)، لكننا لن نفعل ذلك هنا. تذكّر أنَّ استخدام React يمنحنا تنظيمًا لعناصر واجهة المستخدم التي يمكن تحويلها إلى شجرة DOM أو تطبيقاتٍ أخرى. لنصيّر الآن المكوِّن <MySelect> إلى شجرة DOM الافتراضية والتي بدورها ستصيّر إلى شجرة DOM الأساسية داخل صفحة HTML. في شيفرة JavaScript التالية، ستلاحظ أننا أضفنا استدعاءً للدالة ReactDOM.render() في آخر سطر، ومررنا إلى الدالة ReactDOM.render() المكوِّن الذي نريد تصييره (وهو <MySelect>) ومرجعية إلى عنصر HTML موجودٌ في شجرة HTML DOM (وهو <div id="app"></div>) الذي نريد عرض المكوِّن <MySelect> فيه. class MySelect extends React.Component { // MySelect تعريف المكوِّن render(){ var mySelectStyle = { border: '1px solid #999', display: 'inline-block', padding: '5px' }; // JSX استخدام {} للإشارة إلى متغير جافاسكربت داخل // <MyOption> يحتوي على المكون JSX باستخدام <div> إعادة عنصر return ( <div style={mySelectStyle}> <MyOption value="Volvo"></MyOption> <MyOption value="Saab"></MyOption> <MyOption value="Mercedes"></MyOption> <MyOption value="Audi"></MyOption> </div> ); } }; class MyOption extends React.Component { // MyOption تعريف المكون render(){ // JSX باستخدام <div> إعادة عنصر return <div>{this.props.value}</div>; } }; ReactDOM.render(<MySelect />, document.getElementById('app')); لاحظ أنَّ كل ما فعلناه هو إخبار React أين ستبدأ بتصيير المكونات وما هي المكونات التي عليها بدء التصيير بها. بعد ذلك ستصيّر React أيّة مكونات محتواة داخل المكوِّن الأصلي (مثل المكوِّن <MyOption> داخل <MySelect>). انتظر لحظة! ربما تفكِّر الآن أننا لم نُنشِئ العنصر <select> أصلًا، وكل ما فعلناه هو إنشاء قائمة ثابتة عديم الحالة من السلاسل النصية. سنصلح ذلك في الخطوة القادمة. قبل أن نكمل إلى الخطوة القادمة، أحب أن أشير إلى عدم وجود أي تعاملات ضمنية مع شجرة DOM لكي نعرض المكوِّن في شجرة DOM. بعبارةٍ أخرى، لم نستدعِ شيفرة jQuery أثناء إنشاء هذا المكوِّن؛ وجميع التعاملات مع شجرة DOM الفعلية قد أصبحت مجردةً (abstract) عبر استعمال شجرة DOM الافتراضية الخاصة بمكتبة React. في الواقع، عندما نستخدم React فما نفعله هو وصف شجرة DOM الافتراضية التي تأخذها React وتحوِّلها إلى شجرة DOM الفعلية لنا. استخدام حالة React (أي React state) لكي نجعل عنصر <MySelect> الخاص بنا يحاكي عنصر <select> الأصلي في HTML فعلينا أن نضيف حالةً (state) له. فما فائدة عنصر <select> المخطط إذا لم يكن قادرًا على الاحتفاظ بقيمة الاختيار الذي اخترناه. تأتي الحالة (state) عندما يحتوي المكوِّن على نسخة من المعلومات. وبخصوص عنصر <MyOption> المخصص، الحالة هي النص المختار حاليًا أو عدم وجود نص مختار من الأساس. لاحظ أنَّ الحالة تتضمن عادةً أحداثًا تابعة للمستخدم (مثل الفأرة أو لوحة المفاتيح أو حافظة النسخ …إلخ.) أو أحداثًا تابعة للشبكة (أي AJAX) وتستخدم قيمتها لتحديد إن كانت واجهة المستخدم للمكوِّن تحتاج إلى إعادة تصيير (re-render، فتغيير القيمة سيؤدي إلى إعادة التصيير). ترتبط الحالة عادةً بأعلى مكوِّن الذي يُنشِئ مكوِّن UI. كنا في السابق نستخدم الدالة getInitialState() في React لنستطيع ضبط الحالة الافتراضية، فلو أردنا ضبط حالة المكون إلى false (أي لا يوجد أي نص مختار) فسنعيد كائن حالة عند استدعاء الدالة getInitialState() (أي return {selected: false};). دورة حياة الدالة getInitialState() هي استدعاء الدالة مرةً قبل تركيب المكوِّن، وستُستخدَم القيمة المعادة منها كقيمة افتراضية للخاصية this.state. الطريقة السابقة قديمة ولم تعد مستخدمةً إلا إذا كنتَ من محبي الوحدة create-react-class والتي سنأتي على ذكرها لاحقًا، أما في الأصناف في ES6، فنحن نستعمل this.state ضمن الدالة البانية (constructor) للصنف الخاص بالمكون. أي أننا سنكتب في الدالة البانية للصنف MySelect تعريفًا للحالة التي نريدها. هذه نسخة مُحدَّثة من الشيفرة أضفنا فيها الحالة إلى المكوِّن، أنصحك بقراءة التعليقات التي أضعها في الشيفرة والتي تجذب انتباهك إلى التغييرات التي حدثت في الشيفرة. class MySelect extends React.Component { constructor(){ // إضافة الحالة الافتراضية super(); this.state = {selected: false}; // this.state.selected = false; } render(){ var mySelectStyle = { border: '1px solid #999', display: 'inline-block', padding: '5px' }; return ( <div style={mySelectStyle}> <MyOption value="Volvo"></MyOption> <MyOption value="Saab"></MyOption> <MyOption value="Mercedes"></MyOption> <MyOption value="Audi"></MyOption> </div> ); } }; class MyOption extends React.Component { render(){ return <div>{this.props.value}</div>; } }; ReactDOM.render(<MySelect />, document.getElementById('app')); بعد ضبط الحالة الافتراضية، سنستدعي دالة رد نداء (callback function) باسم select التي ستُطلَق عندما يضغط المستخدم على خيارٍ ما. داخل هذه الدالة سنحصل على نص الخيار الذي اختاره المستخدم (عبر المعامل event) وسنستخدمه لضبط الحالة setState للمكوِّن الحالي. لاحظ أننا نستخدم تفاصيل الكائن event المُمرَّر إلى دالة رد النداء select. يُفترَض أنَّ هذا النمط من البرمجة مألوفٌ لديك إن كانت لديك أيّ خبرة مع مكتبة jQuery من قبل. من أهم ما يجب ملاحظته في الشيفرة الآتية هو اتباع التوابع في مكوّنات React المُعرَّفة كأصناف ES6 لنفس القواعد في أصناف ES6 الاعتيادية، يعني هذا أنّها لا تربط this بنسخة الكائن، بل يجب عليك أن تستخدم بشكل صريح التابع .bind(this) في الدالة البانية: class MySelect extends React.Component { constructor(){ // إضافة الحالة الافتراضية super(); this.state = {selected: false}; // this.state.selected = false; this.select = this.select.bind(this); // هذا السطر مهم، راجع الشرح أعلاه } select(event){ // select إضافة الدالة if(event.target.textContent === this.state.selected){ // إزالة التحديد this.setState({selected: false}); // تحديث الحالة }else{ // إضافة التحديد this.setState({selected: event.target.textContent}); // تحديث الحالة } } render(){ var mySelectStyle = { border: '1px solid #999', display: 'inline-block', padding: '5px' }; return ( <div style={mySelectStyle}> <MyOption value="Volvo"></MyOption> <MyOption value="Saab"></MyOption> <MyOption value="Mercedes"></MyOption> <MyOption value="Audi"></MyOption> </div> ); } }; class MyOption extends React.Component { render(){ return <div>{this.props.value}</div>; } }; ReactDOM.render(<MySelect />, document.getElementById('app')); ولكي تحصل مكوِّنات <MyOption> على وصولٍ للدالة select فمررنا إشارةً مرجعيةً إليها عبر خاصيات React (props) من المكوِّن <MySelect> إلى المكوِّن <MyOption>. ولفعل ذلك أضفنا select={this.select} إلى مكونات <MyOption>. بعد ضبط ما سبق، يمكننا إضافة onClick={this.props.select} إلى المكوِّن <MyOption>. أرجو أن يكون واضحًا أنَّ ما فعلناه هو ربط الحدث click الذي سيستدعي الدالة select. تتكفّل React بربط دالة التعامل مع حدث النقر الحقيقي في شجرة DOM نيابةً عنّا. class MySelect extends React.Component { constructor(){ super(); this.state = {selected: false}; this.select = this.select.bind(this); } select(event){ if(event.target.textContent === this.state.selected){ this.setState({selected: false}); }else{ this.setState({selected: event.target.textContent}); } } render(){ var mySelectStyle = { border: '1px solid #999', display: 'inline-block', padding: '5px' }; return ( <div style={mySelectStyle}> <MyOption select={this.select} value="Volvo"></MyOption> <MyOption select={this.select} value="Saab"></MyOption> <MyOption select={this.select} value="Mercedes"></MyOption> <MyOption select={this.select} value="Audi"></MyOption> </div> ); } }; class MyOption extends React.Component { render(){ return <div onClick={this.props.select}>{this.props.value}</div>; } }; ReactDOM.render(<MySelect />, document.getElementById('app')); بعد فعلنا لذلك، يمكننا الآن ضبط الحالة بالنقر على أحد الخيارات؛ وبعبارةٍ أخرى، عندما تنقر على خيارٍ ما فستستدعى الدالة select وتضبط حالة المكوِّن <MySelect>. لكن مستخدم المكوِّن لن يعرف أبدًا أنَّ ذلك قد حصل لأنَّ كل ما فعلناه حتى الآن هو تغيير حالة المكوِّن، ولا توجد أي تغذية بصرية تشير إلى اختيار أي عنصر. لذا لنصلح ذلك. ما علينا فعله الآن هو تمرير الحالة الراهنة إلى المكوِّن <MyOption> لكي يستجيب -بصريًا- إلى تغيير حالة المكوِّن. باستخدام الخاصيات عبر props، سنُمرِّر الحالة selected من المكوِّن <MySelect> إلى المكوِّن <MyOption> بوضع الخاصية state={this.state.selected} في جميع مكونات <MyOption>. أصبحنا نعلم الآن ما هي الحالة (أي this.props.state) والقيمة الحالية (أي this.props.value) للخيار لكي نتحقق إذا كانت الحالة تُطابِق القيمة الموجودة في مكوِّن <MyOption> ما. وإذا كانت تطابقها، فسنعلم أنَّه يجب تحديد هذا الخيار، وسنفعل ذلك باستخدام عبار if بسيطة التي تضيف أنماط تنسيق (selectedStyle) إلى عنصر <div> في JSX إذا كانت الحالة تُطابِق قيمة الخيار الحالي. وفيما عدا ذلك، سنعيد عنصر React مع النمط unSelectedStyle: class MySelect extends React.Component { constructor(){ super(); this.state = {selected: false}; this.select = this.select.bind(this); } select(event){ if(event.target.textContent === this.state.selected){ this.setState({selected: false}); }else{ this.setState({selected: event.target.textContent}); } } render(){ var mySelectStyle = { border: '1px solid #999', display: 'inline-block', padding: '5px' }; return ( <div style={mySelectStyle}> <MyOption state={this.state.selected} select={this.select} value="Volvo"></MyOption> <MyOption state={this.state.selected} select={this.select} value="Saab"></MyOption> <MyOption state={this.state.selected} select={this.select} value="Mercedes"></MyOption> <MyOption state={this.state.selected} select={this.select} value="Audi"></MyOption> </div> ); } }; class MyOption extends React.Component { render(){ var selectedStyle = {backgroundColor:'red', color:'#fff',cursor:'pointer'}; var unSelectedStyle = {cursor:'pointer'}; if(this.props.value === this.props.state){ return <div style={selectedStyle} onClick={this.props.select}>{this.props.value}</div>; }else{ return <div style={unSelectedStyle} onClick={this.props.select}>{this.props.value}</div>; } } }; ReactDOM.render(<MySelect />, document.getElementById('app')); صحيحٌ أنَّ عنصر <select> الذي أنشأناه ليس جميلًا أو كاملًا كما كنتَ ترجو، لكنني أظن أنَّك ترى ما الغرض الذي حققناه. مكتبة React تسمح لك بالتفكير بالعناصر بطريقة منظمة ومهيكلة هيكليةً صحيحة. قبل الانتقال إلى شرح دور شجرة DOM الافتراضية، أود أنَّ أوضِّح أنَّه من غير الضروري استخدام JSX و Babel. يمكنك تخطي هذه الأدوات واستخدام شيفرات JavaScript مباشرة. سأريك نسخةً أخيرةً من الشيفرة بعد تحويل JSX باستخدام Babel. إذا لم ترغب باستخدام JSX فيمكنك أن تكتب الشيفرة الآتية يدويًا بدلًا من الشيفرة التي كتبناها خلال هذا المقال: class MySelect extends React.Component { constructor() { super(); this.state = { selected: false }; this.select = this.select.bind(this); } select(event) { if (event.target.textContent === this.state.selected) { this.setState({ selected: false }); } else { this.setState({ selected: event.target.textContent }); } } render() { var mySelectStyle = { border: '1px solid #999', display: 'inline-block', padding: '5px' }; return React.createElement("div", { style: mySelectStyle }, React.createElement(MyOption, { state: this.state.selected, select: this.select, value: "Volvo" }), React.createElement(MyOption, { state: this.state.selected, select: this.select, value: "Saab" }), React.createElement(MyOption, { state: this.state.selected, select: this.select, value: "Mercedes" }), React.createElement(MyOption, { state: this.state.selected, select: this.select, value: "Audi" })); } }; class MyOption extends React.Component { render() { var selectedStyle = { backgroundColor: 'red', color: '#fff', cursor: 'pointer' }; var unSelectedStyle = { cursor: 'pointer' }; if (this.props.value === this.props.state) { return React.createElement("div", { style: selectedStyle, onClick: this.props.select }, this.props.value); } else { return React.createElement("div", { style: unSelectedStyle, onClick: this.props.select }, this.props.value); } } }; ReactDOM.render(React.createElement(MySelect, null), document.getElementById('app')); فهم دور شجرة DOM الافتراضية (virtual DOM) سأنهي جولتنا بأكثر جوانب React حديثًا بين المطورين، إذ سأتحدث عن شجرة DOM الافتراضية (React virtual DOM). لاحظنا -عبر الأمثلة في هذا المقال- أنَّ التعامل الوحيد مع شجرة DOM الحقيقية أثناء إنشائنا لعنصر <select> خاص بنا هو عندما أخبرنا الدالة ReactDOM.render() أين ستعرض مكوِّنات UI في صفحة HTML (أي عندما عرضناها في <div id="app"></div>). من المرجح أن يكون هذا تعاملك الوحيد مع شجرة DOM الحقيقية عندما تبني تطبيق React من شجرة من المكوِّنات. وهنا تأتي قيمة مكتبة React. فعند استخدامك لها، ليس عليك أن تفكر بشجرة DOM بنفس الطريقة التي كنتَ تفكِّر فيها عند كتابتك لشيفرة jQuery. فمكتبة React تستبدل jQuery عبر تجريد استخدام شجرة DOM. ولأنَّ شجرة DOM الافتراضية حلّت محل شجرة DOM الحقيقية، سمح ذلك بإجراء تحديثات لشجرة DOM الحقيقية مع أداءٍ ممتاز. تبقي شجرة DOM الافتراضية سجلًا بجميع التغيرات في واجهة المستخدم اعتمادًا على الحالة والخاصيات (state و props)، ثم تقارنها بشجرة DOM الحقيقية وتجري أقل مقدار ممكن من التعديلات عليها. بصيغةٍ أخرى، لا تُحدَّث شجرة DOM الحقيقية إلا بأقل قدر ممكن وذلك عند تغيير الحالة أو الخاصيات. صراحةً، هذا المفهوم ليس ثوريًا أو جديدًا، يمكنك فعل المثل باستخدام شيفرة jQuery مكتوبة بعناية، لكنك لن تحتاج إلى التفكير بهذه الأمور عند استخدام React. فشجرة DOM الافتراضية تجري عمليات تحسين الأداء عوضًا عنك، فلا حاجة لأن تقلق حول أي شيء، فكل ذلك يحدث وراء الكواليس ونادرًا ما تحتاج إلى التعامل مع شجرة DOM الحقيقية نفسها. أرغب أن أنهي هذه المقدمة بالقول أنَّ استخدام React يلغي تقريبًا الحاجة إلى استخدام أي مكتبات أخرى مثل jQuery. واستخدام شجرة DOM الافتراضية يريحنا من كثيرٍ من التفاصيل الدقيقة، لكن قيمة مكتبة React لا تكمن في شجرة DOM الافتراضية فقط، وإنما يمكننا أن نعدّ شجرة DOM الافتراضية على أنها الفستق الحلبي المبشور فوق الحلوى؛ فببساطة، قيمة مكتبة React تكون في أنها توفِّر طريقةً سهلةً الإنشاء والصيانة لإنشاء شجرة من مكوِّنات الواجهة الرسومية. تخيل بساطة إنشاء واجهة رسومية إذا بنيتَ تطبيقك باستخدام مكوِّنات React القابلة لإعادة الاستخدام. تذكر هذه السلسلة عندما تريد أن تعرِّف ما هي React. مكتبة React.js هي مكتبة JavaScript التي يمكن استخدامها لبناء واجهات المستخدم، وباستخدام React يمكن للمطورين إنشاء مكونات قابلة لإعادة الاستخدام، وهذه المكونات تُظهِر البيانات وتستطيع تغييرها مع الزمن؛ وتوجد أيضًا مكتبة React Native لبناء تطبيقات للهواتف الذكية باستخدام React. ترجمة وبتصرف للفصل What is React? من كتاب React Enlightenment1 نقطة
-
قبل أن نتعرف سويةً على آلية عمل React، دعنا نتعرف بدايةً على بعض المصطلحات التي ستسهِّل عملية التعليم. سأورد قائمةً من المصطلحات الشائعة، إضافةً إلى تعريفاتها، وسنستعمل هذه المصطلحات أثناء حديثنا عن React. Babel يحوِّل Babel شيفرة JavaScript ES (أي JS 2015 و JS 2016 و JS 2017) إلى شيفرة ES5. إنَّ Babel هي أداة من اختيار مطوري React لكتابة شيفرات ES وتحويل JSX إلى شيفرة ES5. Babel CLI يأتي Babel مع أداة تعمل من سطر الأوامر تسمى Babel CLI، ويمكن أن تستخدم لبناء الملفات من سطر الأوامر. خيارات ضبط المكونات (Component Configuration Options) وهي وسائط الضبط التي تُمرَّر (ككائن) إلى الدالة React.createClass() أو الدالة البانية (في حال كنت تستعمل الأصناف في ES6) مما ينتج نسخةً (instance) من مكوِّن React. توابع دورة حياة المكونات (Component Life Cycle Methods) توابع دورة حياة المكونات هي مجموعة فرعية من أحداث المكونات، المفصولة (اصطلاحيًا) عن الخيارات الأخرى لضبط المكونات، أي هي: componentWillUnmount componentDidUpdate UNSAFE_componentWillUpdate shouldComponentUpdate UNSAFE_componentWillReceiveProps componentDidMount UNSAFE_componentWillMount تُنفَّذ هذه التوابع في نقاط مُحدَّدة من دورة حياة المكوِّن. شجرة DOM (Document Object Model) شجرة DOM هي الواجهة البرمجية لمستندات HTML و XML و SVG، وهي توفِّر تمثيلًا هيكليًا للمستند كشجرة. تُعرِّف DOM الدوال التي تسمح بالوصول إلى الشجرة، لذا يمكنها تغيير بنية المستند وأنماط التنسيق التابعة له ومحتواه. توفِّر DOM تمثيلًا للمستند على شكل مجموعة مهيكلة من العقد (nodes) والكائنات (objects)، والتي تملك مختلف الخاصيات (properties) والتوابع (methods). يمكن أن تملك العقد معالجات أحداث (event handlers) مرتبطة بها، وستستدعى تلك المعالجات عند تفعيل الحدث. باختصار، تصل شجرة DOM بين صفحات الويب ولغات البرمجة. ES5 الإصدار الخامس من معيار ECMAScript. ES6 أو ECMAScript 2015 الإصدار السادس من معيار ECMAScript، والذي يحتوي على إضافات كثيرة على لغة JavaScript. ES7 أو ECMAScript 2016 الإصدار السابع من معيار ECMAScript. ES* تستخدم لتمثيل النسخة الحالية من JavaScript إضافةً إلى الإصدارات المستقبلية، والتي يمكن الكتابة بها باستخدام أدوات مثل Babel. عندما ترى «ES*» فمن المرجح أنَّ المقصود بها هو ES5 و ES6 و ES7 معًا. JSX JSX هي صيغة إضافية اختيارية تشبه XML لمعيار ECMAScript التي يمكن أن تُستخدم لتعريف بنية شجريّة شبيهة بلغة HTML في ملفات JavaScript. ستحوَّل تعابير JSX في ملف JavaScript إلى صياغة JavaScript قبل أن يتمكن محرِّك JavaScript من تفسير الملف. تُستَخدم برمجية Babel عادةً لتحويل تعابير JSX. Node.js Node.js هي بيئة تشغيل مفتوحة المصدر ومتعددة المنصات لكتابة شيفرات JavaScript. بيئة التشغيل Node.js تُفسِّر شيفرات JavaScript باستخدام محرِّك V8. npm npm هو مدير حزم للغة JavaScript نَشَأ من مجتمع Node.js. خاصيات React (أي React props) يمكنك أن تعدّ الخاصيات (props) على أنها خيارات الضبط لعقد React، وفي نفس الوقت يمكنك أن تتخيلها كخاصيات HTML. تملك الخاصيات عدِّة أدوار: يمكن أن تصبح خاصيات HTML، فلو طابقت خاصيةٌ ما إحدى خاصيات HTML فستُضاف كخاصية HTML في شجرة DOM النهائية. الخاصيات المُمرَّرة إلى الدالة createElement() تصبح قيمًا مخزنةً في الكائن prop كنسخة (instance) من React.createElement() أي [INSTANCE].props.[NAME_OF_PROP] تستخدم الخاصيات بكثرة لتمرير قيم إلى المكونات. بعض الخاصيات لها تأثيرات جانبية (مثل key و ref و dangerouslySetInnerHTML). React React هي مكتبة JavaScript تُستخدم لكتابة واجهات للمستخدمة بمرونة وكفاءة وفعالية عالية. مكوِّن React يُنشَأ مكوِّن React باستدعاء الوحدة create-react-class (أو React.Component عند استخدام الأصناف في ES6). هذه الدالة تأخذ كائنًا من الخيارات الذي يُستخدَم لضبط وإنشاء مكونات React. أحد أشهر خيارات الضبط هو الدالة render التي تعيد عقد React أي React nodes. والتالي يمكننك أن تعدّ مكوِّن React على أنه تجريد (abstraction) يحتوي على مكوِّن أو عقدة React واحد أو أكثر. الوحدة create-react-class توفر هذه الوحدة طريقة لإنشاء مكونات React دون إنشاء صنف جديد وجعله مشتقًا من الصنف React.Component. هذه الوحدة موجودة لكتابة شيفرات React.js دون ES6. عقد عناصر React عقد عناصر React (React Element Nodes أو ReactElement) هو تمثيل يشبه عناصر HTML في شجرة DOM يُنشَأ باستخدام React.createElement();. عقد React عقد React (React Nodes أي عقد العناصر والعقد النصية) هو نوع الكائنات الرئيسي في React ويمكن إنشاؤه باستخدام React.createElement('div');. بعبارةٍ أخرى، عقد React هي كائنات تُمثِّل عقد DOM وعقد DOM الأبناء التابعة لها. وهي تمثيلٌ خفيفٌ وعديم الحالة (stateless) وغير قابلٍ للتعديل (immutable) لعقدة DOM. مصانع عقد React مصانع عقد React (React Node Factories) هي دالة تولِّد عقد عنصر React ذات نوعٍ (type) مُحدَّد. كانت هذه الخاصية موجودة في إصدارات سابقة من React.js ثم أهملت. دالة مكون React عديم الحالة أي React Stateless Function Component، وتكون عندما يتألف المكوِّن من الخاصيات فقط، دون حالة، ويمكن أن يكتب المكوِّن كدالة نقية مما يجعلنا نتجنب إنشاء نسخة من مكوِّن React. var MyComponent = function(props){ return <div>Hello {props.name}</div>; }; ReactDOM.render(<MyComponent name="Ahmed" />, app); عقد عناصر React عقد عناصر React (React Text Nodes، أي ReactText) هي تمثيل للعقد النصية في شجرة DOM الوهمية كما في React.createElement('div', null, 'a text node');. شجرة DOM الوهمية (Virtual DOM) Virtual DOM هي شجرة مخزَّنة في ذاكرة JavaScript لعناصر ومكونات React وتُستخدَم لإعادة تصيير (re-render) شجرة DOM بكفاءة عالية (بمعرفة الاختلافات بينها وبين شجرة DOM الحقيقية). Webpack Webpack هو مُحمِّل للوحدات (modules) والمجمِّع (bundler) لها، والذي يأخذ الوحدات (.js أو .css أو .txt …إلخ.) مع اعتمادياتها ويولِّد وسائط ساكنة (static assets) تُمثِّل هذه الوحدات. ترجمة -وبتصرف- للفصل React Semantics من كتاب React Enlightenment1 نقطة