اذهب إلى المحتوى

مدخل إلى صيغة JavaScript Syntax Extension) JSX)


عبد اللطيف ايمش

تعلمنا في المقال السابق كيفية إنشاء عقد React باستخدام شيفرات JavaScript العادية، وسنلقي في هذا المقال نظرةً على إنشاء عقد React باستخدام صيغة JSX. إن لم تقرأ المقال السابق، عقد React، فانتقل إليه أولًا لقراءته ثم عد إلى هذا المقال.

سنستخدم صيغة JSX بعد هذا المقال في بقية الكتاب ما لم نستعمل الدالة React.createElement()‎ لأغراض التوضيح.

بعد انتهائك من قراءة هذا المقال، يمكنك الاطلاع على شرح تفصيلي لجميع ميزات JSX في موسوعة حسوب.

ما هي صيغة JSX؟

JSX هي صيغة شبيهة بصيغة XML أو HTML التي تستخدمها React لتوسعة ECMAScript لكي نستطيع كتابة تعابير شبيهة بلغة XML أو HTML داخل شيفرة JavaScript. هذه الصيغة مهيئة للعمل مع برمجيات التحويل مثل Babel لتحويل النص الشبيه بشيفرات HTML في ملفات JavaScript إلى كائنات JavaScript التي تستطيع محركات JavaScript تفسيرها.

أساسيًا، عند استخدمنا لصيغة JSX يمكننا أن نكتب بنى شبيهة ببنى HTML (أي هياكل من العناصر كما في DOM) بنفس الملف الذي تكتب فيه شيفرة JavaScript، ثم يحوِّل Babel هذه التعابير إلى شيفرة JavaScript حقيقية. وعلى عكس ما جرت عليه العادة بوضع شيفرات JavaScript داخل HTML، تسمح لنا صيغة JSX بوضع شيفرات HTML داخل JavaScript.

تسمح لنا JSX بكتابة شيفرة JavaScript الآتية:

var nav = (
    <ul id="nav">
      <li><a href="#">Home</a></li>
      <li><a href="#">About</a></li>
      <li><a href="#">Clients</a></li>
      <li><a href="#">Contact Us</a></li>
    </ul>
);

وسيحولها Babel إلى الشيفرة الآتية:

var nav = React.createElement(
   "ul",
   { id: "nav" },
   React.createElement(
      "li",
      null,
      React.createElement(
         "a",
         { href: "#" },
         "Home"
      )
   ),
   React.createElement(
      "li",
      null,
      React.createElement(
         "a",
         { href: "#" },
         "About"
      )
   ),
   React.createElement(
      "li",
      null,
      React.createElement(
         "a",
         { href: "#" },
         "Clients"
      )
   ),
   React.createElement(
      "li",
      null,
      React.createElement(
         "a",
         { href: "#" },
         "Contact Us"
      )
   )
);

لذا يمكننا أن نعدّ JSX على أنها اختصار لاستدعاء React.createElement()‎.

فكرة دمج شيفرات HTML و JavaScript في نفس الملف هي فكرة مثيرة للجدال، حاول أن تتجاهل ذلك وتستعملها إذا وجدتها مفيدةً، وإذا لم تجدها مفيدةً فاكتب شيفرة JavaScript الضرورية لإنشاء عقد React يدويًا، فالخيار عائد لك تمامًا. أرى شخصيًا أنَّ JSX توفِّر صيغة مختصرة ومألوفةً لتعريف بنى هيكلية مع الخاصيات اللازمة لها والتي لا تتطلب تعلّم صيغة قوالب خاصة أو تتطلب الخروج من شيفرة JavaScript؛ وكلا الميزتين السابقتين مفيدتان عند إنشاء التطبيقات الكبيرة.

من الواضح أنَّ صيغة JSX أسهل قراءةً وكتابةً من الأهرامات الكبيرة من استدعاءات دوال JavaScript مع تعريف الكائنات داخلها (قارن الشيفرتين السابقتين في هذا القسم لتتأكد من ذلك). أضف إلى ذلك أنَّ فريق تطوير React يعتقد أنَّ JSX أفضل لتعريف واجهات المستخدم من أحد حلول القوالب (مثل Handlebars):

«إنَّ الشيفرة البرمجية والبنى الهيكلية مرتبطتان مع بعضهما بعضًا ارتباطًا وثيقًا. أضف إلى ذلك أنَّ الشيفرات البرمجية معقدة جدًا واستخدام لغات القوالب ستجعل الأمر صعبًا جدًا. وجدنا أنَّ أفضل حل لهذه المشكلة هو توليد شيفرات HTML مباشرةً من شيفرة JavaScript، وبهذا نستطيع استخدام كامل قدرات لغة برمجية حقيقية لبناء واجهات المستخدم.»

ملاحظات

  • لا تفكر في JSX على أنها لغة قوالب، وإنما هي صيغة JavaScript خاصة يمكن تصريفها، أي أنَّ JSX هي صيغة تسمح بتحويل بنى شبيهة ببنى HTML إلى شيفرات JavaScript.

  • أداة Babel هي الأداة التي اختارها فريق تطوير React لتحويل شيفرات ES*‎ و JSX إلى شيفرة ES5. يمكنك معرفة المزيد عن Babel بقراءة توثيقه الرسمي.

  • باستخدام صيغة JSX:

    • أصبح بإمكان الأشخاص غير المتخصصين تقنيًا فهم وتعديل الأجزاء المطلوبة. فيجد مطورو CSS والمصممون صيغة JSX أكثر ألفةً من شيفرة JavaScript.

    • يمكنك استثمار كامل قدرات JavaScript في HTML وتتجنب تعلّم أو استخدام لغة خاصة بالقوالب. لكن اعلم أن JSX ليس محرّك قوالب، وإنما صيغة تصريحية للتعبير عن البنية الهيكلية الشجرية لمكونات UI.

    • سيجد المُصرِّف (compiler) أخطاءً في شيفرة HTML الخاصة بك كنتَ ستغفل عنها.

    • تحث صياغة JSX على فكر استخدام الأنماط السطرية (inline styles) وهو أمرٌ حسن.

  • صيغة JSX منفصلة عن React، ولا تحاول JSX أن تتفق مع أي مواصفة تخص HTML أو XML، وإنما هي مصممة كميزة ECMAScript وهي تشبه HTML ظاهريًا فقط، وتجري كتابة مواصفة JSX كمسودة لكي تُستخدَم من أي شخص كإضافة لصياغة ECMAScript.

  • في صيغة JSX، يجوز استخدام ‎<foo-bar />‎ بمفرده، لكن لا يجوز استخدام <foo-bar>. أي عليك إغلاق جميع الوسوم دومًا.

إنشاء عقد React باستخدام JSX

بإكمالنا لما تعلمناه في المقال الماضي، يجب أن تكون قادرًا على إنشاء عقد React باستخدام الدالة React.createElement()‎. فيمكن مثلًا استخدام هذه الدالة لإنشاء عقد React التي تُمثِّل عقدًا حقيقيةً في HTML DOM إضافةً إلى عقدٍ مخصصة. سأريك حالتي الاستخدام السابقتين في المثال الآتي:

// حقيقية HTML DOM التي تمثِّل عقدة React عقدة
var HTMLLi = React.createElement('li', {className:'bar'}, 'foo');

// مخصصة HTML DOM التي تمثِّل عقدة React عقدة
var HTMLCustom = React.createElement('foo-bar', {className:'bar'}, 'foo');

لاستخدام صيغة JSX بدلًا من React.createElement()‎ لإنشاء هذه العقد، فكل ما علينا فعله هو تبديل استدعاءات الدالة React.createElement()‎ إلى وسوم شبيهة بوسوم HTML التي تُمثِّل عناصر HTML التي تريد إنشاء شجرة DOM الافتراضية بها. يمكننا أن نكتب الشيفرة السابقة بصيغة JSX كما يلي:

// حقيقية HTML DOM التي تمثِّل عقدة React عقدة    
var HTMLLi = <li className="bar">foo</li>;

// مخصصة HTML DOM التي تمثِّل عقدة React عقدة    
var HTMLCustom = <foo-bar className="bar" >foo</foo-bar>;

لاحظ أنَّ صيغة JSX غير محتواة في سلسلة نصية في JavaScript، وتكتبها كأنك تكتب الشيفرة داخل ملف ‎.htmlعادي، وكما ذكرنا لعدّة مرات، ستحوِّل صيغة JSX إلى استدعاءات للدالة React.createElement()‎ باستخدام Babel:

// حقيقية HTML DOM التي تمثِّل عقدة React عقدة
var HTMLLi = <li className="bar">foo</li>;

// مخصصة HTML DOM التي تمثِّل عقدة React عقدة
var HTMLCustom = <foo-bar className="bar" >foo</foo-bar>;

ReactDOM.render(HTMLLi, document.getElementById('app1'));

ReactDOM.render(HTMLCustom, document.getElementById('app2'));

إذا أردتَ تفحص شيفرة HTML الناتجة عن المثال السابق، فستجد أنَّها شبيهة بهذه الشيفرة:

<body>
    <div id="app1"><li class="bar" data-reactid=".0">foo</li></div>
    <div id="app2"><foo-bar class="bar" data-reactid=".1">foo</foo-bar></div>
</body>

إنشاء عقد React باستخدام JSX سهل جدًا كما لو كنتَ تكتب شيفرة HTML داخل ملفات JavaScript.

ملاحظات

  • تدعم JSX صيغة إغلاق الوسوم الخاصة بلغة XML، لذا يمكنك أن تهمل إضافة وسم الإغلاق إذا لم يمتلك العنصر أي أبناء.

  • إذا مررت خاصيات إلى عناصر HTML التي ليست موجودة في مواصفة HTML فلن تعرضها React. أما إذا استخدمتَ عناصر HTML مخصصة (أي أنها ليست قياسية) فستُضاف الخاصيات التي ليست موجودةً في مواصفة HTML إلى العناصر المخصصة (فمثلًا ‎<``x-my-component custom-attribute="foo" />‎).

  • الخاصية class يجب أن تكتب className.

  • الخاصية for يجب أن تكتب htmlFor.

  • الخاصية style تقبل إشارةً مرجعيةً إلى كائنٍ يحتوي على خاصيات CSS بالصيغة المتعارف عليها في JavaScript (أي background-color تصبح backgroundColor).

  • جميع الخاصيات مكتوبة بالصيغة المستخدمة في JavaScript، وذلك بحذف الشرطة وجعل الحرف الذي يليها كبيرًا (أي accept-charset ستصبح acceptCharset).

  • لتمثيل عناصر HTML احرص على كتابة الوسوم بحرفٍ صغير.

  • هذه هي قائمة بجميع خاصيات HTML التي تدعمها React:

accept acceptCharset accessKey action allowFullScreen allowTransparency alt
async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge
charSet checked classID className colSpan cols content contentEditable
contextMenu controls coords crossOrigin data dateTime default defer dir
disabled download draggable encType form formAction formEncType formMethod
formNoValidate formTarget frameBorder headers height hidden high href hrefLang
htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label
lang list loop low manifest marginHeight marginWidth max maxLength media
mediaGroup method min minLength multiple muted name noValidate nonce open
optimum pattern placeholder poster preload radioGroup readOnly rel required
reversed role rowSpan rows sandbox scope scoped scrolling seamless selected
shape size sizes span spellCheck src srcDoc srcLang srcSet start step style
summary tabIndex target title type useMap value width wmode wrap

تصيير JSX إلى DOM

يمكن استخدام الدالة ReactDOM.render()‎ لتصيير تعابير JSX إلى DOM. في الواقع، كل ما تفعله Babel هو تحوي JSX إلى React.createElement()‎.

في المثال الآتي، سنُصيّر العنصر <li> والعنصر المخصص <foo-bar> إلى DOM باستخدام تعابير JSX:

// حقيقية HTML DOM التي تمثِّل عقدة React عقدة
var HTMLLi = <li className="bar">foo</li>;

// مخصصة HTML DOM التي تمثِّل عقدة React عقدة
var HTMLCustom = <foo-bar className="bar" >foo</foo-bar>;

// <div id="app1"></div> إلى HTMLLi باسم React تصيير عقدة
ReactDOM.render(HTMLLi, document.getElementById('app1'));

// <div id="app2"></div> إلى HTMLCustom باسم React تصيير عقدة
ReactDOM.render(HTMLCustom, document.getElementById('app2'));

ستبدو شيفرة HTML كما يلي بعد تصيير العناصر إلى DOM:

<body>
    <div id="app1"><li class="bar" data-reactid=".0">foo</li></div>
    <div id="app2"><foo-bar classname="bar" children="foo" data-reactid=".1">foo</foo-bar></div>
</body>

تذكّر أنَّ Babel يأخذ JSX ويحولها إلى عقد React (أي استدعاءات الدالة React.createElement()‎) ثم باستخدام هذه العقد المُنشَأة باستخدام React (في شجرة DOM الافتراضية) سنُصيّر العناصر إلى شجرة DOM الحقيقية. ما تفعله الدالة ReactDOM.render()‎ هو تحويل عقد React إلى عقد DOM حقيقة ثم إضافتها إلى مستند HTML.

ملاحظات

  • ستستبدل أي عقد DOM داخل عناصر DOM التي سيُصيَّر إليها (أي أنها ستُحذَف ويحلّ المحتوى الجديد محلها).

  • الدالة ReactDOM.render()‎ لا تعدِّل عقدة عنصر DOM الذي تُصيّر React إليه، وإنما تتطلَّب React ملكيةً كاملةً للعقدة النصية عند التصيير، فلا يجدر بك إضافة أبناء أو إزالة أبناء من العقدة التي تضيف React فيها المكوِّن أو العقدة.

  • التصيير إلى شجرة HTML DOM هو أحد الخيارات فقط، فهنالك خياراتٌ أخرى ممكنة، فمثلًا تستطيع التصيير إلى سلسلة نصية (أي ReactDOMServer.renderToString()‎) في جهة الخادم.

  • إعادة تصيير نفس عنصر DOM سيؤدي إلى تحديث العقد الأبناء الحاليين إذا حدث تغييرٌ فيها، أو إذا أُضيفت عقدة عنصر ابن جديدة.

  • لا تستدعي this.render()‎ يدويًا أبدًا، اترك الأمر إلى React.

استخدام تعابير JavaScript داخل JSX

آمل الآن أن يكون واضحًا أنَّ JSX هي صيغة بسيطة ستحوَّل في نهاية المطاف إلى شيفرة JavaScript حقيقة، لكن ماذا سيحدث عندما نريد تضمين شيفرة JavaScript حقيقية داخل JSX؟ كل ما علينا فعله لكتابة تعابير JavaScript داخل JSX هو وضعها ضمن قوسين معقوفين {}.

في شيفرة React الآتية، سنضيف تعبيرًا من تعابير JavaScript (وهو 2+2) محاطًا بقوسين معقوفين {} التي ستُفسَّر من معالج JavaScript:

var label = '2 + 2';
var inputType = 'input';

// JSX لاحظ كيفية استخدام تعابير أو قيم جافاسكربت بين القوسين المعقوفين داخل صيغة 
var reactNode = <label>{label} = <input type={inputType} value={2+2} /></label>;

ReactDOM.render(reactNode, document.getElementById('app'));

ستحوَّل شيفرة JSX إلى النتيجة الآتية:

var label = '2 + 2';
var inputType = 'input';

var reactNode = React.createElement(
  'label',
  null,
  label,
  ' = ',
  React.createElement('input', { type: inputType, value: 2 + 2 })
);

ReactDOM.render(reactNode, document.getElementById('app'));

بعد أن تُفسَّر الشيفرة السابقة من محرِّك JavaScript (أي المتصفح)، فستُقدَّر قيمة تعابير JavaScript وستبدو شيفرة HTML كما يلي:

<div id="app">
    <label data-reactid=".0"><span data-reactid=".0.0">2 + 2</span><span data-reactid=".0.1"> = </span><input type="input" value="4" data-reactid=".0.2"></label>
</div>

لا يوجد شيءٌ معقد في المثال السابق، بعد الأخذ بالحسبان أنَّ الأقواس ستُهرِّب شيفرة JSX. فالقوسان {} سيخبران JSX أنَّ المحتوى الموجود داخلهما هو شيفرة JavaScript فستتركها دون تعديل لكي يفسرها مُحرِّك JavaScript (أي التعبير 2+2) لاحظ أنَّ القوسين {} يمكن أن يستخدما في أي مكان داخل تعابير JSX لطالما كانت نتيجتها هو تعبيرٌ صالحٌ في JavaScript.

استخدام تعليقات JavaScript داخل JSX

يمكنك وضع تعليقات JavaScript في أي مكان في شيفرة JSX عدا المواضع التي تتوقع فيها JSX عقدة React ابن. في هذه الحالة ستحتاج إلى تهريب (escape) التعليق باستخدام {} لكي تعلم JSX أنَّ عليها تمرير المحتوى كشيفرة JavaScript.

تفحص الشيفرة الآتية، واحرص على فهم متى عليك إخبار JSX أن تُهرِّب تعليق JavaScript لكيلا تُنشَأ عقدة React ابن:

var reactNode = <div /*comment*/>{/* use {} here to comment*/}</div>;

إذا لم نضع التعليق في الشيفرة السابقة الموجود داخل العقدة

ضمن القوسين {} فسيحاول Babel تحويل التعليق إلى عقدة React نصية، وسيكون الناتج -غير المتوقع- دون استخدام {} كما يلي:
var reactNode = React.createElement(
  "div",
  null,
  "/* use ",
  " here to comment*/" 
);

مما سينُتِج شيفرة HTML الآتية التي تحتوي على عقد نصية أُنشِئت خطأً:

<div data-reactid=".0">
    <span data-reactid=".0.0">/* use </span><span data-reactid=".0.1"> here to comment*/</span>
</div>

استخدام أنماط CSS داخل JSX

لتعريف أنماط CSS ضمن صيغة JSX، فعلينا تمرير مرجعية إلى كائنٍ يحتوي على خاصيات CSS وقيمها إلى الخاصية style.

سنُهيّئ في بداية المثال الآتي كائن JavaScript باسم styles يحتوي على الأنماط التي نريد تضمينها سطريًا في JSX، ثم سنستخدم القوسين {} للإشارة إلى الكائن الذي يجب أن يُستخدَم كقيمة للأنماط (مثل style={styles}‎):

var styles = {
    color: 'red',
    backgroundColor: 'black',
    fontWeight: 'bold'
};

var reactNode = <div style={styles}>test</div>;

ReactDOM.render(reactNode, document.getElementById('app1'));

لاحظ أنَّ خاصيات CSS المُضمَّنة سطريًا مكتوبة بطريقة كتابة خاصيات CSS في JavaScript، وهذا ضروريٌ لأنَّ JavaScript لا تسمح باستخدام الشرطات – في أسماء الخاصيات.

عند تحويل شيفرة JSX السابقة باستخدام Babel، ثم تفسيرها من محرِّك JavaScript فستكون شيفرة HTML الناتجة:

<div style="color:red;background-color:black;font-weight:bold;" data-reactid=".0">test</div>

ملاحظات

  • يجب أن تبدأ السابقات الخاصة بالمتصفحات (باستثناء ms) بحرفٍ كبير، لهذا السبب تبدأ الخاصية WebkitTransition بحرف W كبير.

  • يجب ألا يفاجئك استخدام الأحرف الكبيرة في أسماء خاصيات CSS بدلًا من الشرطات، فهذه هي الطريقة المتبعة للوصول إلى تلك الخاصيات في شجرة DOM عبر JavaScript (كما في document.body.style.backgroundImage).

  • عند تحديد قيمة بواحدة البكسل، فستضيف React السلسلة النصية "px" تلقائيًا بعد القيم الرقمية باستثناء الخاصيات الآتية:

columnCount fillOpacity flex flexGrow flexShrink fontWeight lineClamp lineHeight
opacity order orphans strokeOpacity widows zIndex zoom

تعريف الخاصيات في JSX

في المقال السابق، ناقشنا تمرير خاصيات إلى الدالة React.createElement(type, props, children)‎ عند إنشاء عقد React. ولمّا كانت صيغة JSX ستحوِّل إلى استدعاءات للدالة React.createElement()‎ فأنت تملك فكرةً (من المقال السابق) كيف تعمل خاصيات React. لكن لمّا كانت JSX تُستخدَم للتعبير عن عناصر HTML فإنَّ الخاصيات المُعرَّفة ستُضاف إلى عنصر HTML الناتج.

في المثال الآتي سأعرِّف عقدة <li> في React باستخدام JSX، ولها خمس خاصيات، لاحظ أنَّ إحداها هي خاصيةٌ غيرُ قياسيةٍ في HTML (وهي foo: 'bar'‎) أما البقية فهي خاصيات HTML عادية:

var styles = {backgroundColor:'red'};
var tested = true;
var text = 'text';

var reactNodeLi = <li id=""
                      data-test={tested?'test':'false'}
                      className="blue"
                      aria-test="test"
                      style={styles}
                      foo="bar">
                          {text}
                  </li>;

ReactDOM.render(reactNodeLi, document.getElementById('app1'));

ستبدو شيفرة JSX بعد تحويلها كما يلي، لاحظي أنَّ الخاصيات أصبح وسائط مُمرَّرة إلى الدالة:

var reactNodeLi = React.createElement(
    'li',
    { id: '',
        'data-test': tested ? 'test' : 'false',
        className: 'blue',
        'aria-test': 'test',
        style: styles,
        foo: 'bar' },
    text
);

عند تصيير العقد reactNodeLi إلى DOM، فستبدو كما يلي:

<div id="app1">
    <li id="true"
        data-test="test"
        class="blue"
        aria-test="test"
        style="background-color:red;"
        data-reactid=".0">
            text
    </li>
</div>

يجب أن تلاحظ الأمور الأربعة الآتية:

  • ترك قيمة إحدى الخاصيات فارغةً سيؤدي إلى جعل قيمتها مساويةً إلى true (أي id=""‎ ستصبح id="true"‎، و test ستصبح test="true"‎).

  • الخاصية foo لن تُضاف إلى العنصر النهائي لأنها ليست خاصية HTML قياسية.

  • لا يمكنك كتابة أنماط سطرية في JSX. عليك أن تُشير إلى كائنٍ يقطع في مجال تعريف شيفرة JSX أو تمرير كائن يحتوي على خاصيات CSS مكتوبةً كخاصيات JavaScript.

  • يمكن أن تُضاف قيم JavaScript ضمن JSX باستخدام القوسين المعقوفين {} (كما في test={text}‎ و data-test={tested?'test':'false'}‎).

ملاحظات

  • إذا كانت خاصيةٌ ما مكررةً فستؤخذ آخر قيمة لها.

  • إذا مررت خاصيات إلى عناصر HTML التي ليست موجودة في مواصفة HTML فلن تعرضها React. أما إذا استخدمتَ عناصر HTML مخصصة (أي أنها ليست قياسية) فستُضاف الخاصيات التي ليست موجودةً في مواصفة HTML إلى العناصر المخصصة (فمثلًا ‎<x-my-component custom-attribute="foo" />‎).

  • الخاصية class يجب أن تكتب className.

  • الخاصية for يجب أن تكتب htmlFor.

  • الخاصية style تقبل إشارةً مرجعيةً إلى كائنٍ يحتوي على خاصيات CSS بالصيغة المتعارف عليها في JavaScript (أي background-color تصبح backgroundColor).

  • خاصيات النماذج في HTML (مثل <input> أو <textarea></textarea> …إلخ.) المُنشَأة كعقد React ستدعم خاصيات التي يمكن تغييرها عبر تفاعل المستخدم مع العنصر؛ وهذه الخاصيات هي value و checked و selected.

  • توفِّر React الخاصيات key و ref و dangerouslySetInnerHTML التي لا تتوافر في DOM وتأخذ دورًا فريدًا.

  • يجب أن تكتب جميع الخاصيات مع حذف الشرطة - وجعل أول حرف يليها مكتوبًا بحرفٍ كبير، أي أنَّ الخاصية accept-charset ستُكتَب acceptCharset.

  • هذه هي خاصيات HTML التي تدعمها تطبيقات React:

accept acceptCharset accessKey action allowFullScreen allowTransparency alt
async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge
charSet checked classID className colSpan cols content contentEditable
contextMenu controls coords crossOrigin data dateTime default defer dir
disabled download draggable encType form formAction formEncType formMethod
formNoValidate formTarget frameBorder headers height hidden high href hrefLang
htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label
lang list loop low manifest marginHeight marginWidth max maxLength media
mediaGroup method min minLength multiple muted name noValidate nonce open
optimum pattern placeholder poster preload radioGroup readOnly rel required
reversed role rowSpan rows sandbox scope scoped scrolling seamless selected
shape size sizes span spellCheck src srcDoc srcLang srcSet start step style
summary tabIndex target title type useMap value width wmode wrap

تعريف الأحداث في JSX

في المقال السابق، شرحنا ووضحنا كيف يمكن أن ترتبط الأحدث مع عقد React. لفعل المثل في JSX عليك إضافة الأحداث ودالة المعالجة الخاصة بها كخاصية لشيفرة JSX التي تُمثِّل عقدة React.

أُخِذ المثال الآتي من المقال السابق ويبيّن طريقة إضافة حدث إلى عقدة React دون استخدام JSX:

var mouseOverHandler = function mouseOverHandler() {
        console.log('you moused over');
    };
var clickhandler = function clickhandler() {
        console.log('you clicked');
    };
var reactNode = React.createElement(
        'div',
        { onClick: clickhandler, onMouseOver: mouseOverHandler },
        'click or mouse over'
    );

ReactDOM.render(reactNode, document.getElementById('app'));

يمكن أن تُكتَب الشيفرة السابقة باستخدام JSX:

var mouseOverHandler = function mouseOverHandler() {
        console.log('you moused over');
    };
var clickHandler = function clickhandler() {
        console.log('you clicked');
    };

var reactNode = <div onClick={clickHandler} onMouseOver={mouseOverHandler} >click or mouse over</div>;

ReactDOM.render(reactNode, document.getElementById('app'));

لاحظ أننا استخدمنا القوسين {} لربط دالة JavaScript إلى الحدث (أي onMouseOver={mouseOverHandler}‎)، وهذه الطريقة تشابه طريقة ربط الأحداث السطرية في DOM.

الأحداث التي تدعمها React موجودةٌ في الجدول الآتي:

نوع الحدث الأحداث خاصيات متعلقة به
الحافظة
  • onCopy
  • onCut
  • onPaste
  • DOMDataTransfer
  • clipboardData
التركيب
  • onCompositionEnd
  • onCompositionStart
  • onCompositionUpdate
  • data

لوحة المفاتيح

  • onKeyDown
  • onKeyPress
  • onKeyUp
  • altKey
  • charCode
  • ctrlKey
  • getModifierState(key)‎
  • key
  • keyCode
  • locale
  • location
  • metaKey
  • repeat
  • shiftKey
  • which

التركيز

  • onChange
  • onInput
  • onSubmit
  • DOMEventTarget
  • relatedTarget

النماذج

  • OnFocus
  • onBlur

 

الفأرة

  • onClick
  • onContextMenu
  • onDoubleClick
  • onDrag
  • onDragEnd
  • onDragEnter
  • onDragExit
  • onDragLeave
  • onDragOver
  • onDragStart
  • onDrop
  • onMouseDown
  • onMouseEnter
  • onMouseLeave
  • onMouseMove
  • onMouseOut
  • onMouseOver
  • onMouseUp
  • altKey
  • button
  • buttons
  • clientX
  • clientY
  • ctrlKey
  • getModifierState(key)‎
  • metaKey
  • pageX
  • pageY
  • DOMEventTarget
  • relatedTarget
  • screenX
  • screenY
  • shiftKey

الاختيار

  • onSelect

 

اللمس

  • onTouchCancel
  • onTouchEnd
  • onTouchMove
  • onTouchStart
  • altKey
  • DOMTouchList
  • changedTouches
  • ctrlKey
  • getModifierState(key)‎
  • metaKey
  • shiftKey
  • DOMTouchList
  • targetTouches
  • DOMTouchList
  • touches

واجهة المستخدم

  • onScroll
  • detail
  • DOMAbstractView
  • view

الدولاب

  • onWheel
  • deltaMode
  • deltaX
  • deltaY
  • deltaZ

الوسائط

  • onAbort
  • onCanPlay
  • onCanPlayThrough
  • onDurationChange
  • onEmptied
  • onEncrypted
  • onEnded
  • onError
  • onLoadedData
  • onLoadedMetadata
  • onLoadStart
  • onPause
  • onPlay
  • onPlaying
  • onProgress
  • onRateChange
  • onSeeked
  • onSeeking
  • onStalled
  • onSuspend
  • onTimeUpdate
  • onVolumeChange
  • onWaiting

 

    الصور

    • onLoad
    • onError

     

    الحركات

    • onAnimationStart
    • onAnimationEnd
    • onAnimationIteration
    • animationName
    • pseudoElement
    • elapsedTime

    الانتقالات

    • onTransitionEnd
    • propertyName
    • pseudoElement
    • elapsedTime

    ملاحظات

    • توحِّد React التعامل مع الأحداث لكي تسلك سلوكًا متماثلًا في جميع المتصفحات.

    • تنطلق الأحداث في React في مرحلة الفقاعات (bubbling phase). لإطلاق حدث في مرحلة الالتقاط (capturing phase) فأضف الكلمة "Capture" إلى اسم الحدث، أي أنَّ الحدث onClick سيصبح onClickCapture).

    • إذا احتجتَ إلى تفاصيل كائن الأحداث المُنشَأ من المتصفح، فيمكنك الوصول إليه باستخدام الخاصية nativeEvent في كائن SyntheticEvent المُمرَّر إلى دالة معالجة الأحداث في React.

    • لا تربط React الأحداث إلى العقد نفسها، وإنما تستخدم «تفويض الأحداث» (event delegation).

    • يجب استخدام e.stopPropagation()‎ أو e.preventDefault()‎ يدويًا لإيقاف انتشار الأحداث بدلًا من استخدام return false;‎.

    • لا تدعم React جميع أحداث DOM، لكن ما يزال بإمكاننا الاستفادة منها باستخدام توابع دورة الحياة في React.

    ترجمة وبتصرف للفصل JavaScript Syntax Extension (a.k.a, JSX)‎ من كتاب React Enlightenment


    تفاعل الأعضاء

    أفضل التعليقات

    لا توجد أية تعليقات بعد



    انضم إلى النقاش

    يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

    زائر
    أضف تعليق

    ×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

      Only 75 emoji are allowed.

    ×   Your link has been automatically embedded.   Display as a link instead

    ×   جرى استعادة المحتوى السابق..   امسح المحرر

    ×   You cannot paste images directly. Upload or insert images from URL.


    ×
    ×
    • أضف...