الفرق بين المراجعتين لصفحة: «ReactNative/platform specific code»
أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE:كتابة شيفرة حسب المنصة في React Native}}</noinclude> عند إنشاء تطبيقٍ متعدّد المنصّات (أو ع...' |
جميل-بيلوني (نقاش | مساهمات) ط مراجعة |
||
(4 مراجعات متوسطة بواسطة 3 مستخدمين غير معروضة) | |||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE:كتابة شيفرة حسب المنصة في React Native}}</noinclude> | <noinclude>{{DISPLAYTITLE:كتابة شيفرة حسب المنصة في React Native}}</noinclude> | ||
عند إنشاء تطبيقٍ متعدّد المنصّات (أو عابرٍ للمنصّات: cross-platform)، ستحتاج إلى إعادة استخدام أكبر | عند إنشاء تطبيقٍ متعدّد المنصّات (أو عابرٍ للمنصّات: cross-platform)، ستحتاج إلى إعادة استخدام أكبر قدرٍ ممكنٍ من الشيفرة، لكن يُمكن أحيانًا أن يكون اختلاف الشيفرة حسب المنصّة منطقيًّا، فقد ترغب مثلًا بإنشاء مكوناتٍ مرئيةٍ منفصلةٍ لنظامي التشغيل iOS وAndroid، بحيث يختلف مظهر التطبيق حسب نظام المستخدِم. | ||
يقدم React Native طريقتين لتنظيم الشيفرة وفصلها حسب المنصّة بسهولة: | يقدم React Native طريقتين لتنظيم الشيفرة وفصلها حسب المنصّة بسهولة: | ||
* استخدام وحدة <code>Platform</code>. | * [[ReactNative/platform specific code#.D8.A7.D9.84.D9.88.D8.AD.D8.AF.D8.A9 Platform|استخدام وحدة <code>Platform</code>.]] | ||
* استخدام امتدادات ملفّات (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 توثيق المشروع]. | ||
==الوحدة 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> | ||
ستُساوي قيمةُ Platform.OS القيمةَ <code>ios</code> عند تشغيل التطبيق على iOS والقيمةَ <code>android</code> عند تشغيله على منصّة Android. | ستُساوي قيمةُ <code>Platform.OS</code> القيمةَ <code>ios</code> عند تشغيل التطبيق على iOS والقيمةَ <code>android</code> عند تشغيله على منصّة Android. | ||
يُمكنك كذلك الاعتماد على التابع Platform. | يُمكنك كذلك الاعتماد على التابع <code>Platform.select</code>، والذي يُعطى كائنًا يحتوي على إحدى المفاتيح التالية <code>'ios'</code> - <code>'android'</code> - <code>'native'</code> - <code>'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: ' | backgroundColor: 'green' | ||
}, | }, | ||
}) | default: { | ||
} | // other platforms, web for example | ||
backgroundColor: 'blue' | |||
} | |||
}) | |||
} | |||
}); | }); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
ستُنتِج الشيفرة أعلاه حاويةً ذات النمط <code>flex: 1</code> على | ستُنتِج الشيفرة أعلاه حاويةً ذات النمط <code>flex: 1</code> على المنصّات كلها، مع خلفية حمراء على منصّة iOS، وخلفية خضراء على Android، وزرقاء على المنصات الأخرى. | ||
ولأنه يقبل أي قيمةٍ | ولأنه يقبل أي قيمةٍ كانت فيمكنك أيضًا استخدام هذا التابع لإعادة مكوّنٍ كاملٍ حسب المنصّة كما هو موضّح أسفله: | ||
<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== | ||
تستخدم الوحدة <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) تحتوي على نسخة نظام التشغيل | على نظام التشغيل 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> وسيُحمّل الملف المناسب عندما تتطلّبه | إن كانت الشيفرة البرمجية الخاصة بالمنصّة لديك أكثر تعقيدًا، فسيتوجّب عليك تقسيم الشيفرة إلى ملفات منفصلة. سيكتشف React Native امتداد الملفّ <code>.ios.</code> أو <code>.android.</code> وسيُحمّل الملف المناسب عندما تتطلّبه المكوّنات الأخرى. | ||
لنقل مثلًا أنّ مشروعك يحتوي على الملفات التاليّة: | لنقل مثلًا أنّ مشروعك يحتوي على الملفات التاليّة: | ||
سطر 81: | سطر 93: | ||
يُمكنك استيراد المكوّن كما يلي: | يُمكنك استيراد المكوّن كما يلي: | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
import BigButton from './BigButton'; | |||
</syntaxhighlight> | </syntaxhighlight> | ||
سيختار React Native الملفّ الصحيح تلقائيًا حسب النظام المُشغَّل. | سيختار React Native الملفّ الصحيح تلقائيًا حسب النظام المُشغَّل. | ||
== الامتدادات الخاصة في Native (أو مشاركة الشيفرة مع الويب و NodeJS) == | |||
يمكنك استخدام الامتداد <code>.native.js</code> عندما تحتاج مشاركة الوحدة بين [[Node.js|NodeJS]] والويب Web وبين React Native، ولا يوجد فيها اختلافات بين Android و iOS، وهذا مفيد بشكلٍ خاصٍ للمشاريع التي فيها شيفرة شائعة مشتركة بين React Native و [[React|ReactJS]]. | |||
مثلًا لنفرض أن مشروعنا يحوي الملفات التالية:<syntaxhighlight lang="javascript"> | |||
Container.js # (Web bundler) أو أي مجمع ويب Webpack أو Rollup يختار بواسطة | |||
Container.native.js # (Metro) iOS و Android لكلا المنصتين 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]] | ||
[[تصنيف:React Native Docs]] |
المراجعة الحالية بتاريخ 13:32، 9 أكتوبر 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) iOS و Android لكلا المنصتين React Native يختار بواسطة أي مجمع
يمكننا طلبها دون الحاجة للامتداد .native
بالشكل:
import Container from './Container';
ملاحظة: يجب ضبط إعدادات مجمّع الويب (Web bundler) ليتجاهل الامتداد .native.js
لنتجنب الحاجة لشيفرة غير مستخدمة في مجمّع المنتج، وبالتالي تقليص الحجم النهائي للمجمّع.