كتابة شيفرة حسب المنصة في React Native

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث

عند إنشاء تطبيقٍ متعدّد المنصّات (أو عابرٍ للمنصّات: 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) iOS و Android لكلا المنصتين React Native يختار بواسطة أي مجمع

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

import Container from './Container';

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

مصادر