جافا سكريبت XML

JSX (يُشار إليه أحيانًا باسم JavaScript XML ) هو امتدادٌ شبيهٌ بلغة XML لبنية لغة JavaScript . [ 2 ] أُنشئ JSX في البداية بواسطة فيسبوك لاستخدامه مع React ، وقد اعتُمد لاحقًا من قِبل العديد من أُطر عمل الويب . [ 3 ] : 5 [ 4 ] : ​​11 وباعتباره اختصارًا برمجيًا ، يُحوَّل JSX عادةً إلى استدعاءات دوال JavaScript متداخلة تُشابه في بنيتها JSX الأصلي.

عند استخدامها مع TypeScript ، يكون امتداد الملف .tsx . [ 5 ]

عملية

يتطلب الكود المكتوب بلغة JSX تحويلاً باستخدام أداة مثل Babel قبل أن تتمكن متصفحات الويب من فهمه. [ 6 ] [ 3 ] : 5 تتم هذه المعالجة عادةً أثناء عملية بناء البرنامج قبل نشر التطبيق .

يجب على المترجم (مثل Babel) وضع افتراضات حول طبيعة استخدام JSX، وإلا فلن يعرف إلى ماذا يحول وسوم JSX. في حالة Babel (المذكور أدناه)، نستخدمه في وضع يفترض أن الوسوم ستُستخدم مع React، لذا فهو يحول وسوم JSX إلى استدعاءات دوال لبيئة تشغيل React JSX، والتي تُرجع قيمًا تُطابق التمثيل الداخلي لهذه الوسوم. [ 7 ]@babel/plugin-transform-react-jsx ، الذي يستخدمه Babel لـ JSX، يوفر بعض المرونة للتكيف مع منصات أخرى من خلال السماح بتحديد توجيهات بديلة تحل محل React.createElementو React.Fragment. [ 7 ]

ترميز

تتضمن الأمثلة التالية كلاً من كود React-JSX/TSX والناتج المحوّل من Babel.

مثال أساسي

رمز بورصة تورنتوالناتج المُحوَّل (Babel)
استيراد React من 'react' ;const App : React.FC = () => { return ( < div > < p > Header </ p > < p > Content </ p > < p > Footer </ p > </ div > ); }تصدير التطبيق افتراضياً ؛
import React from 'react' ; import { jsx as _jsx , jsxs as _jsxs } from "react/jsx-runtime" ; const App = () => { return /*#__PURE__*/ _jsxs ( "div" , { children : [ /*#__PURE__*/ _jsx ( "p" , { children : "Header" }), /*#__PURE__*/ _jsx ( "p" , { children : "Content" }), /*#__PURE__*/ _jsx ( "p" , { children : "Footer" })] }); }; export default App ;

يشير التعليق /*#__PURE__*/الذي أضافه Babel إلى أن الاستدعاء المُعلَّم هو لدالة خالصة ، وهو أمر مهم للخطوات اللاحقة مثل تقليل حجم الملفات غير المستخدمة . [ 8 ] ولأنه غير ضروري لعمل الكود، فقد تم حذف هذا التعليق من الأمثلة التالية لتسهيل القراءة.

يشير ناتج المُترجم أعلاه إلى ناتج من React 17 والإصدارات الأحدث. أما في الإصدارات الأقدم، فسيكون الناتج أبسط بكثير:

const App = () = > { return React.createElement ( " div " , null , React.createElement ( "p" , null , "Header" ) ) , React.createElement ( "p" , null , " Content") ), React.createElement ( " p" , null , " Footer " )); } ; export default App ;

لا تزال الواجهة الكلاسيكية شائعة الاستخدام بين مستخدمي JSX الذين لا يستخدمون React.

العناصر المتداخلة

يجب تغليف العناصر المتعددة الموجودة على نفس المستوى في عنصر واحد، مثل العنصر <div>الموضح أعلاه، أو جزء محدد بواسطة <Fragment>أو بصيغته المختصرة <>، أو إرجاعه كمصفوفة. [ 9 ] [ 10 ] [ 4 ] : ​​68-69

صفات

توفر لغة JSX مجموعة من سمات العناصر المصممة لمحاكاة تلك التي توفرها لغة HTML. كما يمكن تمرير سمات مخصصة إلى المكون. [ 11 ] ستتلقى المكونات جميع السمات كخصائص (props).

أسماء سمات JSX الصالحة هي معرّفات JSX صالحة (أسماء متغيرات)، وتختلف عن معرّفات ECMAScript بشكل أساسي في السماح باستخدام -علامة الطرح (-) في غير موضع البداية. وهذا يُسهّل استخدام سمات HTML التي تحتوي على شرطات مثل <a> data-*و <b> aria-role. أما السمات التي لا تزال تحتوي على أحرف غير صالحة، فيمكن تدوينها باستخدام الصيغة [ 2 ]{... spread} .

رمز بورصة تورنتوالناتج المُحوَّل (Babel)
<a href="https://en.wikipedia.org" data-note="Wikipedia" { ... { ": tricky-property-name ":a }} // قد تحتوي خاصية XML على نقطتين رأسيتين وتبدأ بهما > ويكيبيديا </a> ;
React.createElement ( "a" , { href : "https://en.wikipedia.org" , "data-note" : " Wikipedia" , ":tricky-property-name" : a , }, " Wikipedia" , );

مكونات مخصصة

"العلامات" المخصصة (المكونات) هي ببساطة وظائف جافا سكريبت التي تقبل أسلوب استدعاء محدد.

كود JSXالناتج المُحوَّل (Babel)
class Hello extends Component { render () { return < h1 > Hello , { this . props . name } ! </ h1 >; } }دالة جيلو ({ الاسم }) { إرجاع < h1 > جيلو ، { الاسم } ! </ h1 >; }export default function App () { return ( <> < Hello name = "Sarah" /> < Jello name = "Connor" /> </> ); }
class Hello extends Component { render () { return React . createElement ( "h1" , null , "Hello, " , this . props . name , "!" ); } }دالة Jello ({ name }) { return React . createElement ( "h1" , null , "Jello, " , name , "!" ); }دالة App () { return React.createElement ( React.Fragment , null , React.createElement ( Hello , { name : "Sarah " , } ) , React.createElement ( Jello , { name : " Connor " , } ) , ) ; }

هنا name="Connor"يصبح الأمر مجرد خيار { name: "Connor" }.

يمكن تعريف المكونات التي تحتوي على مكونات التغليف باستخدام childrenالسمة التي رأيناها بالفعل في الناتج المحوّل:

كود JSXالناتج المُحوَّل (Babel)
const Wrapper = ( props ) => { return ( < div style = {{ backgroundColor : 'lightgray' , padding : '20px' , border : '1px solid black' }}> < h2 > داخل الغلاف : </ h2 > { props . children } </ div > ); }; < Wrapper > < p > فقرة </ p > < p > فقرة أخرى ! < / p > </ Wrapper >
const Wrapper = ( props ) => { return React.createElement ( " div" , { style : { backgroundColor : "lightgray" , padding : "20px" , border : "1px solid black" , } , }, React.createElement ( "h2" , null , " Inside the Wrapper:" ) , props.children , ) ; } ;React.createElement ( Wrapper , null , React.createElement ( "p" , null , " Paragraph " ) ) , React.createElement ( "p" , null , " Another one!" ), ) ;

أسماء وسوم JSX الصحيحة هي معرّفات JSX صالحة (أسماء متغيرات)، مما يعني أنه يمكن استخدام وسوم XML وHTML التي تحتوي على واصلة دون أي مشكلة. مع ذلك، لا يمكن أن تحتوي المكونات المخصصة على أسماء تحتوي على واصلة بسبب قيود قواعد ECMAScript. [ 2 ]

تعبيرات جافا سكريبت

يمكن استخدام تعابير جافا سكريبت (وليس العبارات{} ) داخل JSX باستخدام الأقواس المعقوفة : [ 4 ] : ​​14-16

كود JSXالناتج المُحوَّل (Babel)
< h1 >{ 10 + 1 }</ h1 >
React.createElement ( " h1" , null , 10 + 1 ) ;

سيُظهر المثال أعلاه ما يلي:

<h1> 11 </h1>

التعبيرات الشرطية

لا يمكن استخدام عبارات if-else داخل JSX، ولكن يمكن استخدام التعبيرات الشرطية بدلاً منها. سيتم عرض المثال أدناه كسلسلة نصية لأن قيمة تساوي 1.{i===1?'true':'false'}'true'i

رمز بورصة تورنتوالناتج المُحوَّل (Babel)
استيراد React من 'react' ;const App : React.FC = () => { const i : number = 1 ;return ( <div> <h1> { i === 1 ? ' true ' : ' false ' } </h1> </div> ) ; }تصدير التطبيق افتراضياً ؛
import React from 'react' ; const App = () => { const i = 1 ; return ( React.createElement ( " div" , null , React.createElement ( " h1 " , null , i === 1 ? "true" : " false" ), ) ); }; export default App ;

سيؤدي ما سبق إلى:

<div> <h1> true </h1> </div>

يمكن استخدام الدوال وJSX في الشروط: [ 4 ] : ​​88-90

رمز بورصة تورنتوالناتج المُحوَّل (Babel)
استيراد React من 'react' ;const App : React.FC = () => { const sections : number [] = [ 1 , 2 , 3 ];return ( <div> { sections.map (( n , i ) => ( /* 'key' هي سمة خاصة بـ React لتتبع عناصر القائمة وتغييراتها */ / * يجب أن يكون كل 'key' فريدًا * / < div key = { " section- " + n } > القسم { n } { i === 0 && <span> ( first ) </span> } </div> ) ) } </div> ) ; }تصدير التطبيق افتراضياً ؛
استيراد React من 'react' ;const App = () => { const sections = [ 1 , 2 , 3 ]; return React . createElement ( "div" , null , sections . map (( n , i ) => React . createElement ( "div" , { key : "section-" + n }, "Section " , n , " " , i === 0 && React . createElement ( "span" , null , "(first)" ), ), ), ); };تصدير التطبيق افتراضياً ؛

سيؤدي ما سبق إلى:

<div> <div> القسم 1 <span> ( الأول ) < / span > </div> <div> القسم 2 </div> <div> القسم 3 </div> </div>

بابل: براغماس

تُتيح برامج تحويل الدوال مثل Babel إمكانية استهداف استدعاءات الدوال الأخرى غير تلك الموجودة في React. هنا، يتم توجيه Babel لاستدعاء الدالة التالية tagبدلاً fragمن ذلك:

رمز بورصة تورنتوالناتج المُحوَّل (Babel)
// @jsx tag // @jsxfrag frag const App = () => { const sections = [ 1 , 2 , 3 ]; return ( < div > { sections . map (( n , i ) => ( < div key = { "section-" + n }> القسم { n } { i === 0 && < span >( first )</ span >} </ div > ))} </ div > ); };
// @jsx tag // @jsxfrag frag const App = () => { const sections = [ 1 , 2 , 3 ]; return tag ( "div" , null , sections . map (( n , i ) => tag ( "div" , { key : "section-" + n }, "Section " , n , " " , i === 0 && tag ( "span" , null , "(first)" )), ), ); };

باستخدام إصدارات مختلفة من tagو frag، يمكن إنتاج تمثيلات مختلفة للمدخلات:

كود جافا سكريبتمخرجات البرنامج
// شجرة الكائنات. // يتم تمثيل الأجزاء كمصفوفات. دالة frag (... children ) { return children ; }// يتم تمثيل الوسوم ككائنات function tag ( name , attrs , ... children ) { // يؤدي تسطيح المصفوفة إلى فك أجزاءها // لا يزال يتعين التعامل مع "false" const kids = [] for ( x of children . flat ( Infinity )) { if ( x === false || x === null || x === undefined ) { if ( kids . at ( - 1 ) === " " ) kids . pop () } else kids . push ( x ) } return { name , children : kids , ...( attrs && { attrs })} }console.log ( JSON.stringify ( App ( ) ) ) ;
{ "name" : "div" , "children" : [ { "name" : "div" , "attrs" : { "key" : "section-1" }, "children" : [ "Section " , 1 , " " , { "name" : "span" , "children" : [ "(first)" ] } ] }, { "name" : "div" , "attrs" : { "key" : "section-2" }, "children" : [ "Section " , 2 ] }, { "name" : "div" , "attrs" : { "key" : "section-3" }, "children" : [ "Section " , 3 ] } ] }
// دالة إخراج شبيهة بـ Pug frag (... children ) { let kids = []; for ( const x of children ) { // النص يبدأ بـ | if ( ! Array . isArray ( x )) kids . push ( "| " + x ); else kids . push (... x . flat ( Infinity )); } }دالة tag ( الاسم ، السمات ، ... الأبناء ) { const indent = " " ; const attrStr = Object.entries ( attrs || {}) . map (([ k , v ]) => ` $ { k } =" ${ v } "` ) .join ( " , " ); const head = ` $ { name }${ attrStr ? `( ${ attrStr } )` : "" } ` ; let kids = [ ]; for ( const x of frag ( children ) ) { if ( x === false ) { if ( kids.at ( -1 ) === " | " ) kids.pop ( ) ; } else kids.push ( x ) ; } if ( kids.length == 1 ) // صيغة مختصرة لـ elem>text ولتداخل العناصر return kids [ 0 ] .startsWith ( "| " ) ? [ ` ${ head } ${ kids [ 0 ]. substr ( 2 ) } ` ] : [ ` ${ head } : ${ kids [ 0 ] } ` ]; return [ head , ... kids . map (( line ) => indent + line )]; }console.log ( App (). join ( '\n' ) ) ;
div div ( key= "section-1" ) | القسم | 1 | span (first) div ( key= "section-2" ) | القسم | 2 div ( key= "section-3" ) | القسم | 3 

اللهجات

يشمل ما سبق عملية التحويل من JSX إلى كود ECMAScript. وكما هو موضح في قسم "pragma"، فإن كود ECMAScript الذي يستقبل الكائنات المشتقة من JSX حرٌّ في التعامل مع هذه البيانات كما يشاء.

  • تقوم تطبيقات الواجهة الأمامية، مثل React، عادةً بترجمة هياكل البيانات هذه إلى استدعاءات دوال تُعالج نموذج كائن المستند (DOM) للصفحة. كما تحتوي هذه المكتبات على إصدارات عرض من جانب الخادم، والتي تُنتج، عبر معالجة نموذج كائن المستند "بدون متصفح"، صفحة ويب عادية بتنسيق HTML أو XML عن طريق تسلسل نموذج كائن المستند. [ 12 ]
  • قد تختار تطبيقات الواجهة الخلفية إنشاء HTML أو XML مباشرةً عن طريق تجميع السلاسل النصية، مما يجعلها بمثابة محرك قوالب. [ 13 ]
  • قد لا يكون للتطبيقات المتخصصة (الموضحة أعلاه) أي علاقة بـ HTML أو XML على الإطلاق.

فيما يتعلق بـ HTML و XML، فإن أكثر مجالات الاختلاف شيوعًا هي التعامل مع السمات وإعداد المكونات المتاحة.

صفات

الأسماء

على الرغم من أن JSX يحدد كيفية تحليل السمات ، وأن Babel يلتزم باتفاقية حول كيفية نقلها إلى أكواد ECMAScript الأخرى ، إلا أن أياً منهما لا يحدد كيفية ربط هذه السمات بسمات HTML وXML الفعلية. على سبيل المثال، يستخدم React الاتفاقية التالية لتقليل الحاجة إلى {... spread}الصيغة: [ 14 ]

  • أسماء السمات الأبجدية الرقمية البسيطة لم تتغير.
  • يتم تحويل أسماء السمات التي تحتوي على واصلات من لغة HTML إلى نمط CamelCase، باستثناء السمتين `<header>` data-*و`< aria-*header>`. وهذا يتوافق مع واجهة برمجة تطبيقات JavaScript DOM.
  • xlink:*يتم تحويل أسماء السمات إلى نمط CamelCase، على سبيل المثال xink:hrefتصبح xlinkHref.

يحتوي مُعرِض DOM الخاص بـ React على قائمة مُسبقة من السمات التي يتعرف عليها. بعض هذه السمات مُخصصة للتحويل إلى HTML/XML، والبعض الآخر للاستخدام الداخلي. في وضع الإنتاج (غير التطوير)، لا يُسمح إلا بهذه السمات في وسوم الإخراج، إلا إذا كان الوسم "svg" أو "math". [ 15 ]

قيم

تُطبّق سمة HTML styleمجموعة من أنماط CSS على العنصر المُضمّن بها. ولتسهيل الاستخدام، لا يقبل React-DOM تمرير هذه القيمة كسلسلة نصية فحسب، بل ككائن JavaScript أيضًا. فبدلًا من `<style>` ، يُمكن كتابة ` <style>`. تُحوّل دالة `style>` الكائن تلقائيًا إلى تنسيق السلسلة النصية الصحيح. وتُجرى عملية إعادة تسمية مماثلة باستخدام نمط CamelCase لتبسيط استخدام الأنماط ذات الأسماء التي تحتوي على واصلات. [ 16 ]<div style={"color:" + clr}><div style={{ color: clr }}>

يسمح React-DOM أيضًا بتمرير دوال JavaScript بدلاً من السلاسل النصية كقيم لسمات معالج الأحداث. [ 16 ]

عناصر

بحسب لغة الإخراج، قد تتوفر مكونات مختلفة (تبدو كـ"وسوم" HTML/XML). على سبيل المثال، تأتي وسوم HTML في React من مكتبة `<script>` react-dom، والتي لا تُستخدم عند استهداف لغة أخرى. قد يُعرّف وقت التشغيل أيضًا بعض المكونات مسبقًا: `<script>` هو أحد هذه الأمثلة، على الرغم من أنه أصبح عالميًا بفضل اصطلاح Babel. [ 17 ]<Fragment>

انظر أيضاً

مراجع

  1. "التحديث الأولي للموقع الإلكتروني · facebook/jsx@c40e9b6" . GitHub .
  2. 1 2 3 "مسودة: مواصفات JSX" . JSX . فيسبوك . تم الاطلاع عليه بتاريخ 7 أبريل 2018 .
  3. 1 2 لارسن، جون (2021). React Hooks in Action With Suspense and Concurrent Mode . مانينغ. ISBN 978-1720043997.
  4. 1 2 3 4 ويروش، روبن (14 سبتمبر 2018). الطريق إلى رد الفعل . لينبب. ISBN 978-1720043997.
  5. "الوثائق - JSX" . www.typescriptlang.org . تم الاطلاع عليه بتاريخ 13 يوليو 2025 .
  6. فيشر، لودوفيكو (2017-09-06). React for Real: Front-End Code, Untangled . Pragmatic Bookshelf. ISBN 9781680504484.
  7. 1 2 "@babel/plugin-transform-react-jsx · Babel" . babeljs.io .
  8. "compiler-notations-spec/pure-notation-spec.md at main · javascript-compiler-hints/compiler-notations-spec" . GitHub .
  9. كلارك، أندرو (26 سبتمبر 2017). "React v16.0§ أنواع الإرجاع الجديدة للعرض: الأجزاء والسلاسل النصية" . مدونة React .
  10. "React.Component: render" . React .
  11. كلارك، أندرو (26 سبتمبر 2017). "React v16.0§ دعم سمات DOM المخصصة" . مدونة React .
  12. "createRoot – React" . react.dev .
  13. "html/benchmarks at master · kitajs/html" . GitHub .
  14. "مكونات React DOM - React" . react.dev .
  15. "react/packages/react-dom-bindings/src/client/ReactDOMComponent.js at 64b4605cb82367fa78a08b99bbee1c800e6af21a · facebook/react" . GitHub .
  16. 1 2 "المكونات الشائعة (على سبيل المثال) - React" . react.dev .
  17. "مكونات React المدمجة - React" . react.dev .