الفرق بين المراجعتين ل"React/composition vs inheritance"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
(أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE:الفرق بين التركيب والوراثة في React}}</noinclude>')
 
سطر 1: سطر 1:
 
<noinclude>{{DISPLAYTITLE:الفرق بين التركيب والوراثة في React}}</noinclude>
 
<noinclude>{{DISPLAYTITLE:الفرق بين التركيب والوراثة في React}}</noinclude>
 +
تمتلك React نموذج قوي للتركيب (composition) ونوصي باستخدام التركيب بدلًا من الوراثة (inheritance) لإعادة استخدام الشيفرة بين المُكوِّنات.
 +
 +
سننظر في هذا القسم إلى بعض المشاكل التي بسببها قد يستخدم المُطوِّر الجديد على React الوراثة، وسنرى كيفيّة حلّها باستخدام التركيب.
 +
 +
== مفهوم الاحتواء ==
 +
لا تعرف بعض المُكوِّنات العناصر الأبناء لها مُسبقًا، وهو أمر شائع بشكل خاص بالنسبة لمُكوِّن القائمة الجانبيّة <code>Sidebar</code> أو مربّع الحوار <code>Dialog</code>.
 +
 +
نوصي بأن تستخدم تلك المُكوِّنات الخاصيّة <code>children</code> لتمرير العناصر بشكل مباشر إلى ناتجها:<syntaxhighlight lang="javascript">
 +
function FancyBorder(props) {
 +
  return (
 +
    <div className={'FancyBorder FancyBorder-' + props.color}>
 +
      {props.children}
 +
    </div>
 +
  );
 +
}
 +
 +
</syntaxhighlight>يُتيح هذا للمُكوِّنات الأخرى بأن تُمرِّر عناصر أبناء لها عن طريق التداخل في JSX:<syntaxhighlight lang="javascript">
 +
function WelcomeDialog() {
 +
  return (
 +
    <FancyBorder color="blue">
 +
      <h1 className="Dialog-title">
 +
        أهلًا
 +
      </h1>
 +
      <p className="Dialog-message">
 +
        شكرًا لك لزيارة موقعنا
 +
      </p>
 +
    </FancyBorder>
 +
  );
 +
}
 +
 +
</syntaxhighlight>[https://codepen.io/gaearon/pen/ozqNOV?editors=0010 جرّب المثال على موقع CodePen].
 +
 +
يُمرَّر أي شيء بداخل العنصر <code><FancyBorder></code> إلى المُكوِّن <code>FancyBorder</code> عبر الخاصيّة <code>children</code>. بما أنّ المُكوِّن <code>FancyBorder</code> يُصيِّر <code>{props.children}</code> بداخل عنصر <code>[[HTML/div|<nowiki><div></nowiki>]]</code>، فستظهر العناصر المُمرَّرة بداخل الناتج النهائي.
 +
 +
أحيانًا قد تحتاج إلى تمرير عناصر مُتعدِّدة. في تلك الحالات يجب أن تفعل ذلك بطريقتك الخاصّة بدلًا من استخدام <code>children</code>، كما يلي:<syntaxhighlight lang="javascript">
 +
function SplitPane(props) {
 +
  return (
 +
    <div className="SplitPane">
 +
      <div className="SplitPane-left">
 +
        {props.left}
 +
      </div>
 +
      <div className="SplitPane-right">
 +
        {props.right}
 +
      </div>
 +
    </div>
 +
  );
 +
}
 +
 +
function App() {
 +
  return (
 +
    <SplitPane
 +
      left={
 +
        <Contacts />
 +
      }
 +
      right={
 +
        <Chat />
 +
      } />
 +
  );
 +
}
 +
 +
</syntaxhighlight>[https://codepen.io/gaearon/pen/gwZOJp?editors=0010 جرّب المثال على موقع CodePen].
 +
 +
إنّ عناصر React مثل ‎<Contacts />‎ و ‎<Chat />‎ هي مُجرّد كائنات، لذلك بإمكانك تمريرها كخاصيّات props مثل أي بيانات أخرى. قد يُذكِّرك ذلك بمفهوم المداخل (slots) في مكتبات أخرى، ولكن لا توجد حدود لما يُمكِنك تمريره كخاصيّات props في React.
 +
 +
== التخصيص ==
 +
أحيانًا نُفكّر بالمُكوِّنات على أنّها حالات خاصّة لمُكوِّنات أخرى، فمثلًا قد نقول أنّ مُكوِّن مربّع الترحيب WelcomeDialog هو حالة خاصّة من مربّع الحوار Dialog.
 +
 +
يُمكِن تحقيق ذلك في React عن طريق استخدام التركيب (composition) حيث يُصيِّر المُكوِّن الأكثر خصوصيّة المُكوِّن الأكثر عموميّة ويُعد له الخاصيّات:

مراجعة 12:08، 21 يوليو 2018

تمتلك React نموذج قوي للتركيب (composition) ونوصي باستخدام التركيب بدلًا من الوراثة (inheritance) لإعادة استخدام الشيفرة بين المُكوِّنات.

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

مفهوم الاحتواء

لا تعرف بعض المُكوِّنات العناصر الأبناء لها مُسبقًا، وهو أمر شائع بشكل خاص بالنسبة لمُكوِّن القائمة الجانبيّة Sidebar أو مربّع الحوار Dialog.

نوصي بأن تستخدم تلك المُكوِّنات الخاصيّة children لتمرير العناصر بشكل مباشر إلى ناتجها:

function FancyBorder(props) {
  return (
    <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
    </div>
  );
}

يُتيح هذا للمُكوِّنات الأخرى بأن تُمرِّر عناصر أبناء لها عن طريق التداخل في JSX:

function WelcomeDialog() {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        أهلًا
      </h1>
      <p className="Dialog-message">
        شكرًا لك لزيارة موقعنا
      </p>
    </FancyBorder>
  );
}

جرّب المثال على موقع CodePen.

يُمرَّر أي شيء بداخل العنصر <FancyBorder> إلى المُكوِّن FancyBorder عبر الخاصيّة children. بما أنّ المُكوِّن FancyBorder يُصيِّر {props.children} بداخل عنصر <div>، فستظهر العناصر المُمرَّرة بداخل الناتج النهائي.

أحيانًا قد تحتاج إلى تمرير عناصر مُتعدِّدة. في تلك الحالات يجب أن تفعل ذلك بطريقتك الخاصّة بدلًا من استخدام children، كما يلي:

function SplitPane(props) {
  return (
    <div className="SplitPane">
      <div className="SplitPane-left">
        {props.left}
      </div>
      <div className="SplitPane-right">
        {props.right}
      </div>
    </div>
  );
}

function App() {
  return (
    <SplitPane
      left={
        <Contacts />
      }
      right={
        <Chat />
      } />
  );
}

جرّب المثال على موقع CodePen.

إنّ عناصر React مثل ‎<Contacts />‎ و ‎<Chat />‎ هي مُجرّد كائنات، لذلك بإمكانك تمريرها كخاصيّات props مثل أي بيانات أخرى. قد يُذكِّرك ذلك بمفهوم المداخل (slots) في مكتبات أخرى، ولكن لا توجد حدود لما يُمكِنك تمريره كخاصيّات props في React.

التخصيص

أحيانًا نُفكّر بالمُكوِّنات على أنّها حالات خاصّة لمُكوِّنات أخرى، فمثلًا قد نقول أنّ مُكوِّن مربّع الترحيب WelcomeDialog هو حالة خاصّة من مربّع الحوار Dialog.

يُمكِن تحقيق ذلك في React عن طريق استخدام التركيب (composition) حيث يُصيِّر المُكوِّن الأكثر خصوصيّة المُكوِّن الأكثر عموميّة ويُعد له الخاصيّات: