الفرق بين المراجعتين ل"ReactNative/platform specific code"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
(←‏الوحدة Platform: تمت إضافة فقرات)
سطر 1: سطر 1:
 
<noinclude>{{DISPLAYTITLE:كتابة شيفرة حسب المنصة في React Native}}</noinclude>
 
<noinclude>{{DISPLAYTITLE:كتابة شيفرة حسب المنصة في React Native}}</noinclude>
عند إنشاء تطبيقٍ متعدّد المنصّات (أو عابرٍ للمنصّات: cross-platform)، ستحتاج إلى إعادة استخدام أكبر قدر ممكن من الشيفرة. لكن يُمكن أحيانًا أن يكون اختلاف الشيفرة حسب المنصّة منطقيًّا، فقد ترغب مثلًا بإنشاء مكونات مرئية منفصلة لنظامي التشغيل iOS وAndroid، بحيث يختلف مظهر التطبيق حسب نظام المستخدم.
+
عند إنشاء تطبيقٍ متعدّد المنصّات (أو عابرٍ للمنصّات: cross-platform)، ستحتاج إلى إعادة استخدام أكبر قدرٍ ممكنٍ من الشيفرة، لكن يُمكن أحيانًا أن يكون اختلاف الشيفرة حسب المنصّة منطقيًّا، فقد ترغب مثلًا بإنشاء مكوناتٍ مرئيةٍ منفصلةٍ لنظامي التشغيل iOS وAndroid، بحيث يختلف مظهر التطبيق حسب نظام المستخدِم.
  
 
يقدم React Native طريقتين لتنظيم الشيفرة وفصلها حسب المنصّة بسهولة:
 
يقدم React Native طريقتين لتنظيم الشيفرة وفصلها حسب المنصّة بسهولة:
سطر 7: سطر 7:
 
* [[ReactNative/platform specific code#.D8.A7.D9.85.D8.AA.D8.AF.D8.A7.D8.AF.D8.A7.D8.AA .D8.A7.D9.84.D9.85.D9.84.D9.81.D8.A7.D8.AA .D8.AD.D8.B3.D8.A8 .D8.A7.D9.84.D9.85.D9.86.D8.B5.D8.A9|استخدام امتدادات ملفّات (file extensions) محدّدة حسب المنصّة.]]
 
* [[ReactNative/platform specific code#.D8.A7.D9.85.D8.AA.D8.AF.D8.A7.D8.AF.D8.A7.D8.AA .D8.A7.D9.84.D9.85.D9.84.D9.81.D8.A7.D8.AA .D8.AD.D8.B3.D8.A8 .D8.A7.D9.84.D9.85.D9.86.D8.B5.D8.A9|استخدام امتدادات ملفّات (file extensions) محدّدة حسب المنصّة.]]
  
قد تحتوي بعض المكوّنات على خاصيّات تعمل على منصّة واحدة فقط. تُوضَع تعليقات لجميع هذه الخاصيّات باستخدام العلامة ‎<code>@platform</code>‎ إضافةً إلى شارة صغيرة بجوارها على [https://facebook.github.io/react-native/docs/getting-started توثيق المشروع].
+
قد تحتوي بعض المكوّنات على خاصيّات تعمل على منصّةٍ واحدةٍ فقط، تُوضَع تعليقاتٌ لجميع هذه الخاصيّات باستخدام العلامة ‎<code>@platform</code>‎ إضافةً إلى شارةٍ صغيرةٍ بجوارها على [https://facebook.github.io/react-native/docs/getting-started توثيق المشروع].
  
 
==الوحدة Platform==
 
==الوحدة Platform==
يوفر React Native وحدةً تكتشف المنصّة التي يعمل عليها التطبيق. يمكنك استخدامها لكتابة شيفرة خاصّة بكل منصّة. استخدم هذا الخيار عندما تختلف أجزاءٌ صغيرةٌ فقط من المكوّن حسب المنصّة.
+
يوفر React Native وحدةً تكتشف المنصّة التي يعمل عليها التطبيق، يمكنك استخدامها لكتابة شيفرةٍ خاصّةٍ بكل منصّة، استخدم هذا الخيار عندما تختلف أجزاءٌ صغيرةٌ فقط من المكوّن حسب المنصّة.
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
import {Platform, StyleSheet} from 'react-native';
+
import { Platform, StyleSheet } from 'react-native';
  
 
const styles = StyleSheet.create({
 
const styles = StyleSheet.create({
   height: Platform.OS === 'ios' ? 200 : 100,
+
   height: Platform.OS === 'ios' ? 200 : 100
 
});
 
});
 
</syntaxhighlight>
 
</syntaxhighlight>
سطر 21: سطر 21:
 
ستُساوي قيمةُ <code>Platform.OS</code> القيمةَ ‎<code>ios</code>‎ عند تشغيل التطبيق على iOS والقيمةَ ‎<code>android</code>‎ عند تشغيله على منصّة Android.
 
ستُساوي قيمةُ <code>Platform.OS</code> القيمةَ ‎<code>ios</code>‎ عند تشغيل التطبيق على iOS والقيمةَ ‎<code>android</code>‎ عند تشغيله على منصّة Android.
  
يُمكنك كذلك الاعتماد على التابع <code>Platform.select</code>، والذي يُعطى كائنًا يحتوي على قيمتي <code>Platform.OS</code> كمفاتيح، ويُعيدُ القيمة حسب المنصّة التي يشتغل عليها التطبيق.
+
يُمكنك كذلك الاعتماد على التابع <code>Platform.select</code>، والذي يُعطى كائنًا يحتوي على إحدى المفاتيح التالية <code>'ios'،'android'،'native'،'default'</code>، ويُعيدُ القيمة الأكثر مناسبةً للمنصّة التي نعمل عليها، فإذا كنا نستخدم هاتفًا فسيأخذ المفتاحان <code>ios</code> و <code>android</code>الأفضلية، وإذا لم يحدَّد أحدهما فسيستخدم المفتاح  <code>native</code>، ثم المفتاح <code>default</code>
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
import {Platform, StyleSheet} from 'react-native';
+
import { Platform, StyleSheet } from 'react-native';
  
 
const styles = StyleSheet.create({
 
const styles = StyleSheet.create({
سطر 30: سطر 30:
 
     ...Platform.select({
 
     ...Platform.select({
 
       ios: {
 
       ios: {
         backgroundColor: 'red',
+
         backgroundColor: 'red'
 
       },
 
       },
 
       android: {
 
       android: {
         backgroundColor: 'blue',
+
         backgroundColor: 'green'
 
       },
 
       },
     }),
+
      default: {
   },
+
        // other platforms, web for example
 +
        backgroundColor: 'blue'
 +
      }
 +
     })
 +
   }
 
});
 
});
 
</syntaxhighlight>
 
</syntaxhighlight>
ستُنتِج الشيفرة أعلاه حاويةً ذات النمط ‎<code>flex: 1</code>‎ على كلا المنصّتين، مع خلفية حمراء على منصّة iOS، وخلفية زرقاء على Android.
+
ستُنتِج الشيفرة أعلاه حاويةً ذات النمط ‎<code>flex: 1</code>‎ على المنصّات كلها، مع خلفية حمراء على منصّة iOS، وخلفية خضراء على Android، وزرقاء على المنصات الأخرى.
  
ولأنه يقبل أي قيمةٍ كيفما كانت، فيمكنك أيضًا استخدام هذا التابع لإعادة مكوّنٍ كاملٍ حسب المنصّة كما هو موضّح أسفله:
+
ولأنه يقبل <code>أي قيمةٍ</code> كانت فيمكنك أيضًا استخدام هذا التابع لإعادة مكوّنٍ كاملٍ حسب المنصّة كما هو موضّح أسفله:
  
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 
const Component = Platform.select({
 
const Component = Platform.select({
 
   ios: () => require('ComponentIOS'),
 
   ios: () => require('ComponentIOS'),
   android: () => require('ComponentAndroid'),
+
   android: () => require('ComponentAndroid')
 +
})();
 +
 
 +
<Component />;
 +
</syntaxhighlight><syntaxhighlight lang="javascript">
 +
const Component = Platform.select({
 +
  native: () => require('ComponentForNative'),
 +
  default: () => require('ComponentForWeb')
 
})();
 
})();
  
 
<Component />;
 
<Component />;
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 
==اكتشاف نسخة Android==
 
==اكتشاف نسخة Android==
يمكن على نظام التشغيل Android استخدام الوحدة ‎<code>Platform</code>‎ للحصول على نسخة النظام الذي يعمل عليه التطبيق:
+
تستخدم الوحدة ‎<code>Platform</code> على نظام التشغيل Android ‎ للحصول على نسخة النظام الذي يعمل عليه التطبيق:
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
import {Platform} from 'react-native';
+
import { Platform } from 'react-native';
  
 
if (Platform.Version === 25) {
 
if (Platform.Version === 25) {
سطر 61: سطر 73:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
==اكتشاف نسخة iOS==
 
==اكتشاف نسخة iOS==
على نظام التشغيل iOS، قيمة ‎<code>Version</code>‎ هي نتيجة ‎<code>-[UIDevice systemVersion]</code>‎، وهي سلسلة نصيّة (string) تحتوي على نسخة نظام التشغيل الحاليّة. مثلًا يُمكن لنسخة النظام أن تساويَ السلسلة النصيّة ‎<code>"10.3"</code>‎. وللحصول على رقم النسخة الرئيسي (major version number) على iOS، فيُمكنك استخدام الدالة [[JavaScript/parseInt|‎<code>parseInt</code>‎]]:
+
على نظام التشغيل iOS، قيمة ‎<code>Version</code>‎ هي نتيجة ‎<code>-[UIDevice systemVersion]</code>‎، وهي سلسلة نصيّة (string) تحتوي على نسخة نظام التشغيل الحاليّة. مثلًا يُمكن لنسخة النظام أن تساويَ السلسلة النصيّة ‎"10.3"‎. وللحصول على رقم النسخة الرئيسي (major version number) على iOS، فيُمكنك استخدام:
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
import {Platform} from 'react-native';
+
import { Platform } from 'react-native';
  
 
const majorVersionIOS = parseInt(Platform.Version, 10);
 
const majorVersionIOS = parseInt(Platform.Version, 10);
سطر 72: سطر 84:
  
 
==امتدادات الملفات حسب المنصة==
 
==امتدادات الملفات حسب المنصة==
إن كانت الشيفرة البرمجية الخاصة بالمنصّة لديك أكثر تعقيدًا، فسيتوجّب عليك تقسيم الشيفرة إلى ملفات منفصلة. سيكتشف React Native امتداد الملفّ ‎<code>.ios.</code>‎ أو ‎<code>.android.</code>‎ وسيُحمّل الملف المناسب عندما تتطلّبه (‎<code>require</code>‎) المكوّنات الأخرى.
+
إن كانت الشيفرة البرمجية الخاصة بالمنصّة لديك أكثر تعقيدًا، فسيتوجّب عليك تقسيم الشيفرة إلى ملفات منفصلة. سيكتشف React Native امتداد الملفّ ‎<code>.ios.</code>‎ أو ‎<code>.android.</code>‎ وسيُحمّل الملف المناسب عندما تتطلّبه المكوّنات الأخرى.
  
 
لنقل مثلًا أنّ مشروعك يحتوي على الملفات التاليّة:
 
لنقل مثلًا أنّ مشروعك يحتوي على الملفات التاليّة:
سطر 81: سطر 93:
 
يُمكنك استيراد المكوّن كما يلي:
 
يُمكنك استيراد المكوّن كما يلي:
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
const BigButton = require('./BigButton');
+
import BigButton from './BigButton';
 
</syntaxhighlight>
 
</syntaxhighlight>
 
سيختار React Native الملفّ الصحيح تلقائيًا حسب النظام المُشغَّل.
 
سيختار React Native الملفّ الصحيح تلقائيًا حسب النظام المُشغَّل.
  
إذا كنت تعتمد على شيفرة React Native الخاصّة بك في تطبيق ويب كذلك، فيمكنك أيضًا استخدام الاسم ‎<code>BigButton.native.js</code>‎ ليُستخدَم من طرف كلّ من iOS وAndroid، بينما سيستخدم تطبيق الويب الملفّ ‎<code>BigButton.js</code>.
+
== الامتدادات الخاصة في Native (أو مشاركة الشيفرة مع الويب و NodeJS) ==
 +
يمكنك استخدام الامتداد<code>.native.js</code> عندما تحتاج مشاركة الوحدة بين NodeJS و Web وبين React Native، ولا يوجد فيها اختلافات بين Android و iOS، وهذا مفيد بشكلٍ خاصٍ للمشاريع التي فيها شيفرة شائعة مشتركة بين React Native و ReactJS.
 +
 
 +
مثلًا لنفرض أن مشروعنا يحوي الملفات التالية:<syntaxhighlight lang="javascript">
 +
Container.js #  (Web bundler) أو أي  مجمع ويب  Webpack أو Rollup يختار بواسطة
 +
Container.native.js #    (Metro) Android and iOS لكلا المنصتين React Native يختار بواسطة أي مجمع
 +
 
 +
</syntaxhighlight>يمكننا طلبها دون الحاجة للامتداد <code>.native</code> بالشكل:<syntaxhighlight lang="javascript">
 +
import Container from './Container';
 +
</syntaxhighlight>ملاحظة: يجب ضبط إعدادات مجمّع الويب ( Web bundler ) ليتجاهل الامتداد <code>.native.js</code> لنتجنب الحاجة لشيفرة غير مستخدمة في مجمّع المنتج، وبالتالي تقليص الحجم النهائي للمجمّع.
 +
 
 
== مصادر ==
 
== مصادر ==
 
* [https://facebook.github.io/react-native/docs/platform-specific-code#platform-specific-extensions صفحة Platform Specific Code في توثيق React Native الرسمي.]
 
* [https://facebook.github.io/react-native/docs/platform-specific-code#platform-specific-extensions صفحة Platform Specific Code في توثيق React Native الرسمي.]
 
[[تصنيف:ReactNative]]
 
[[تصنيف:ReactNative]]

مراجعة 19:43، 19 مارس 2021

عند إنشاء تطبيقٍ متعدّد المنصّات (أو عابرٍ للمنصّات: cross-platform)، ستحتاج إلى إعادة استخدام أكبر قدرٍ ممكنٍ من الشيفرة، لكن يُمكن أحيانًا أن يكون اختلاف الشيفرة حسب المنصّة منطقيًّا، فقد ترغب مثلًا بإنشاء مكوناتٍ مرئيةٍ منفصلةٍ لنظامي التشغيل iOS وAndroid، بحيث يختلف مظهر التطبيق حسب نظام المستخدِم.

يقدم React Native طريقتين لتنظيم الشيفرة وفصلها حسب المنصّة بسهولة:

قد تحتوي بعض المكوّنات على خاصيّات تعمل على منصّةٍ واحدةٍ فقط، تُوضَع تعليقاتٌ لجميع هذه الخاصيّات باستخدام العلامة ‎@platform‎ إضافةً إلى شارةٍ صغيرةٍ بجوارها على توثيق المشروع.

الوحدة Platform

يوفر React Native وحدةً تكتشف المنصّة التي يعمل عليها التطبيق، يمكنك استخدامها لكتابة شيفرةٍ خاصّةٍ بكل منصّة، استخدم هذا الخيار عندما تختلف أجزاءٌ صغيرةٌ فقط من المكوّن حسب المنصّة.

import { Platform, StyleSheet } from 'react-native';

const styles = StyleSheet.create({
  height: Platform.OS === 'ios' ? 200 : 100
});

ستُساوي قيمةُ Platform.OS القيمةَ ‎ios‎ عند تشغيل التطبيق على iOS والقيمةَ ‎android‎ عند تشغيله على منصّة Android.

يُمكنك كذلك الاعتماد على التابع Platform.select، والذي يُعطى كائنًا يحتوي على إحدى المفاتيح التالية 'ios'،'android'،'native'،'default'، ويُعيدُ القيمة الأكثر مناسبةً للمنصّة التي نعمل عليها، فإذا كنا نستخدم هاتفًا فسيأخذ المفتاحان ios و androidالأفضلية، وإذا لم يحدَّد أحدهما فسيستخدم المفتاح native، ثم المفتاح default

import { Platform, StyleSheet } from 'react-native';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    ...Platform.select({
      ios: {
        backgroundColor: 'red'
      },
      android: {
        backgroundColor: 'green'
      },
      default: {
        // other platforms, web for example
        backgroundColor: 'blue'
      }
    })
  }
});

ستُنتِج الشيفرة أعلاه حاويةً ذات النمط ‎flex: 1‎ على المنصّات كلها، مع خلفية حمراء على منصّة iOS، وخلفية خضراء على Android، وزرقاء على المنصات الأخرى.

ولأنه يقبل أي قيمةٍ كانت فيمكنك أيضًا استخدام هذا التابع لإعادة مكوّنٍ كاملٍ حسب المنصّة كما هو موضّح أسفله:

const Component = Platform.select({
  ios: () => require('ComponentIOS'),
  android: () => require('ComponentAndroid')
})();

<Component />;
const Component = Platform.select({
  native: () => require('ComponentForNative'),
  default: () => require('ComponentForWeb')
})();

<Component />;

اكتشاف نسخة Android

تستخدم الوحدة ‎Platform على نظام التشغيل Android ‎ للحصول على نسخة النظام الذي يعمل عليه التطبيق:

import { Platform } from 'react-native';

if (Platform.Version === 25) {
  console.log('Running on Nougat!');
}

اكتشاف نسخة iOS

على نظام التشغيل iOS، قيمة ‎Version‎ هي نتيجة ‎-[UIDevice systemVersion]‎، وهي سلسلة نصيّة (string) تحتوي على نسخة نظام التشغيل الحاليّة. مثلًا يُمكن لنسخة النظام أن تساويَ السلسلة النصيّة ‎"10.3"‎. وللحصول على رقم النسخة الرئيسي (major version number) على iOS، فيُمكنك استخدام:

import { Platform } from 'react-native';

const majorVersionIOS = parseInt(Platform.Version, 10);
if (majorVersionIOS <= 9) {
  console.log('Work around a change in behavior');
}

امتدادات الملفات حسب المنصة

إن كانت الشيفرة البرمجية الخاصة بالمنصّة لديك أكثر تعقيدًا، فسيتوجّب عليك تقسيم الشيفرة إلى ملفات منفصلة. سيكتشف React Native امتداد الملفّ ‎.ios.‎ أو ‎.android.‎ وسيُحمّل الملف المناسب عندما تتطلّبه المكوّنات الأخرى.

لنقل مثلًا أنّ مشروعك يحتوي على الملفات التاليّة:

BigButton.ios.js
BigButton.android.js

يُمكنك استيراد المكوّن كما يلي:

import BigButton from './BigButton';

سيختار React Native الملفّ الصحيح تلقائيًا حسب النظام المُشغَّل.

الامتدادات الخاصة في Native (أو مشاركة الشيفرة مع الويب و NodeJS)

يمكنك استخدام الامتداد.native.js عندما تحتاج مشاركة الوحدة بين NodeJS و Web وبين React Native، ولا يوجد فيها اختلافات بين Android و iOS، وهذا مفيد بشكلٍ خاصٍ للمشاريع التي فيها شيفرة شائعة مشتركة بين React Native و ReactJS.

مثلًا لنفرض أن مشروعنا يحوي الملفات التالية:

Container.js #  (Web bundler) أو أي  مجمع ويب  Webpack أو Rollup يختار بواسطة 
Container.native.js #    (Metro) Android and iOS لكلا المنصتين React Native يختار بواسطة أي مجمع

يمكننا طلبها دون الحاجة للامتداد .native بالشكل:

import Container from './Container';

ملاحظة: يجب ضبط إعدادات مجمّع الويب ( Web bundler ) ليتجاهل الامتداد .native.js لنتجنب الحاجة لشيفرة غير مستخدمة في مجمّع المنتج، وبالتالي تقليص الحجم النهائي للمجمّع.

مصادر