كتابة شيفرة حسب المنصة في 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
لنتجنب الحاجة لشيفرة غير مستخدمة في مجمّع المنتج، وبالتالي تقليص الحجم النهائي للمجمّع.