الفرق بين المراجعتين لصفحة: «ReactNative/sectionlist»
لا ملخص تعديل |
جميل-بيلوني (نقاش | مساهمات) طلا ملخص تعديل |
||
(5 مراجعات متوسطة بواسطة 3 مستخدمين غير معروضة) | |||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE:المكون SectionList في ReactNative}}</noinclude> | |||
وهي | وهي واجهةٌ عالية الأداء لتصيير القوائم المقسّمة، ومن أهمّ ميّزاتها: | ||
* | * منصّةٌ متعدّدةٌ (cross-platform). | ||
* تدعم | * ردود نداءٍ قابلةٌ للضبط والعرض. | ||
* تدعم ترويسة (header) القائمة. | |||
* تدعم تذييل (footer) القائمة. | * تدعم تذييل (footer) القائمة. | ||
* تدعم فاصل | * تدعم فاصل العنصر. | ||
* تدعم ترويسة القسم. | * تدعم ترويسة القسم. | ||
* تدعم فاصل الأقسام. | * تدعم فاصل الأقسام. | ||
* تدعم | * تدعم تصيير العناصر والمعطيات غير المتجانسة (Heterogeneous). | ||
* تدعم السحب للتحديث (Pull to Refresh). | * تدعم السحب للتحديث (Pull to Refresh). | ||
* تدعم تحميل | * تدعم تحميل التّمرير (Scroll loading). | ||
يمكن استخدام واجهة أبسط مثل <code>[ | يمكن استخدام واجهة أبسط مثل <code>[[ReactNative/flatlist|FlatList]]</code> عند عدم الحاجة لدعم الأقسام. | ||
__toc__ | |||
== مثال == | |||
* [https://snack.expo.dev/@hsoubwiki/sectionlist-example-function-component مثال لمكوِّن دالّة (Function Component)] | |||
<syntaxhighlight lang="javascript">import React from "react"; | |||
<syntaxhighlight lang="javascript"> | import { StyleSheet, Text, View, SafeAreaView, SectionList, StatusBar } from "react-native"; | ||
import React from "react"; | |||
import { | |||
} from "react-native | |||
const DATA = [ | const DATA = [ | ||
سطر 69: | سطر 63: | ||
container: { | container: { | ||
flex: 1, | flex: 1, | ||
paddingTop: StatusBar.currentHeight, | |||
marginHorizontal: 16 | marginHorizontal: 16 | ||
}, | }, | ||
سطر 86: | سطر 80: | ||
}); | }); | ||
export default App; | export default App; </syntaxhighlight> | ||
* [https://snack.expo.dev/@hsoubwiki/sectionlist-example-class-component مثال لمكوِّن صنف (Class Component)] | |||
<syntaxhighlight lang="javascript">import React, { Component } from "react"; | |||
import { StyleSheet, Text, View, SafeAreaView, SectionList, StatusBar } from "react-native"; | |||
<syntaxhighlight lang="javascript"> | |||
import React, { Component } from "react"; | |||
import { | |||
} from "react-native | |||
const DATA = [ | const DATA = [ | ||
سطر 121: | سطر 105: | ||
]; | ]; | ||
Item = ({ title }) => ( | const Item = ({ title }) => ( | ||
<View style={styles.item}> | <View style={styles.item}> | ||
<Text style={styles.title}>{title}</Text> | <Text style={styles.title}>{title}</Text> | ||
سطر 147: | سطر 131: | ||
container: { | container: { | ||
flex: 1, | flex: 1, | ||
paddingTop: StatusBar.currentHeight, | |||
marginHorizontal: 16 | marginHorizontal: 16 | ||
}, | }, | ||
سطر 164: | سطر 148: | ||
}); | }); | ||
export default App; | export default App; </syntaxhighlight> | ||
يعد هذا المكون غلافًا ملائمًا للمكوّن الأساسيّ <code>[[ReactNative/virtualizedlist|VirtualizedList]]</code>, لذا يرث خاصّيّاته (كذلك خاصّيّات <code>[[ReactNative/scrollview|ScrollView]]</code>) مع مراعاة ما يلي: | |||
* لا تُحفظ الحالة الداخلية عند تمرير المحتوى خارج نافذة التصيير، لذا يجب التأكد من حفظ البيانات ضمن عنصر البيانات أو في المخازن الخارجية، مثل: Flux، أو Redux، أو Relay. | |||
* يُعَدّ هذا المكوّن من النوع الصافي <code>PureComponent</code> أي أنّه لن يُعاد تصييره عندما تبقى قيم الخاصيات <code>Props</code> متساويةً سطحيًا (shallow-equal)، لذا يجب التأكد من أن كلّ ما تعتمد عليه الدّالة <code>renderItem</code> يمرّر لها كخاصّيّةٍ (مثل <code>extraData</code>)، بحيث لا تحتوي على المساواة الصارمة <code>===</code> بعد التحديثات، وإلا فلن تُحدّث الواجهة عند التّغيير، وهذا يتضمّن الخاصيّة <code>data</code> وحالة المكوّن الأب. | |||
* يصيّر المحتوى بصورة غير متزامنة خارج نافذة الواجهة وذلك لتقييد الذاكرة وتأمين تمريرٍ سلسٍ، مما يعني أنه يمكن التمرير أسرع من معدّل التعبئة (fill rate) مما يؤدي لظهور محتوىً فارغٍ للحظة، وهذا عبارة عن مقايضة (tradeoff) يمكن تعديلها لتناسب احتياجات كلّ تطبيق، ونعمل على تحسينه حاليًّأ. | |||
* تبحث القائمة -افتراضيًّا- عن الخاصيّة <code>key</code> لكل عنصر لتستخدمها مثل مفتاح [[React]]، غير أنه يمكن استخدام الخاصيّة <code>keyExtractor</code> المخصّصة على أساس بديل. | |||
== الخاصيات == | |||
موروثة من خاصيّات <code>[[ReactNative/scrollview|ScrollView]]</code> . | |||
=== <code>renderItem</code> === | |||
المُصيّر الافتراضي لكل عنصرٍ في كلّ قسمٍ، ويمكن تجاوزها عل أساس كلّ قسم، ويجب أن تعيد عنصر <code>React</code>. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
| | | دالة (function) | ||
| | | نعم | ||
|} | |} | ||
* <code>item</code> (كائن) | تمرَّر دالة التصيير ككائن له المفاتيح التالية: | ||
* <code>index</code> (عدد) | |||
* <code>section</code> (كائن) | * <code>'item'</code> (كائن): كائن العنصر والمحدد في المفتاح <code>data</code> الخاصّ بالقسم. | ||
* <code>separator</code> (كائن) | * <code>'index'</code> (عدد): دليل العنصر في القسم. | ||
** <code>highlight</code> (دالة) | * <code>'section'</code> (كائن): كائن القسم الكامل كما هو محدّدٌ في <code>sections</code>. | ||
** <code>unhighlight</code> (دالة) | * <code>'separator'</code> (كائن): كائن له المفاتيح التالية: | ||
** <code>updateProps</code> (دالة) | **<code>'highlight'</code> (دالة): <code>() => void</code>. | ||
*** <code>select</code> (قيمة | ** <code>'unhighlight'</code> (دالة): <code>() => void</code>. | ||
*** <code>newProps</code> (كائن). | ** <code>'updateProps'</code> (دالة): <code>(select, newProps) => void</code>. | ||
***<code>'select'</code> (قيمة متعدّدة): قيمها المحتملة <code>'leading'</code> أو <code>'trailing'</code>. | |||
*** <code>'newProps'</code> (كائن). | |||
=== <code>sections</code> === | |||
تمثّل البيانات الفعلية تصييرها، كما هو الحال مع الخاصيّة <code>data</code> في <code>[[ReactNative/flatlist|FlatList]]</code>. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
|مصفوفة من | | مصفوفة من النوع Section (انظر في الأسفل) | ||
|نعم | | نعم | ||
|} | |} | ||
===<code> | === <code>extraData</code> === | ||
خاصّيّةٌ تبيّن للقائمة حاجتها لإعادة التصيير (على اعتبار أنها تنفّذ <code>PureComponent</code>)، وتوضع فيها المعلومات التي تحتاجها الدوال (<code>renderItem</code> والترويسة والتذييل وغيرها) وهي غير موجودةٍ في الخاصية <code>data</code>. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
|أي شيء (any) | | أي شيء (any) | ||
|لا | | لا | ||
|} | |} | ||
===<code> | === <code>initialNumToRender</code> === | ||
تحدد عدد العناصر | |||
تحدد عدد العناصر المصيّرة في الدفعة الأولى، والتي ستكون كافيةً لملء الشاشة لا أكثر، مع ملاحظة أن لن يتم استبدال عناصر الواجهة الأولى كجزء من عملية التصيير بالنوافذ (windowed rendering)، تُستبدل فيه عناصر نافذة الواجهة الحالية بعناصر النافذة التالية أثناء التمرير لتحسين الأداء)، وذلك للمحافظة على فاعلية التمرير للأعلى. | |||
القيمة الافتراضية: 10. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
|عدد (number) | | عدد (number) | ||
|لا | | لا | ||
|} | |} | ||
===<code> | === <code>inverted</code> === | ||
تقوم بعكس اتجاه التّمرير، باستخدام تحويل مقياس الرسم ذي القيمة <code>1-</code>. | |||
القيمة الافتراضية <code>false</code>. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
| | | (boolean) | ||
|لا | | لا | ||
|} | |} | ||
===<code> | === <code>ItemSeparatorComponent</code> === | ||
يُصيّر بين العناصر ولكن لا في الأعلى أو الأسفل، ويزوَّد افتراضيًّا بالخاصيات التالية: | |||
* <code>highlighted</code> | |||
* <code>section</code> | |||
* <code>[leading/trailing][Item/Section]</code>، | |||
كما تحتوي الدالة <code>renderItem</code> الخاصة بالواجهة <code>[[ReactNative/view|View]]</code> على <code>separators.highlight</code>، و <code>separators.unhighlight</code> والمستخدمة لتحديث الخاصيّة <code>highlighted</code>، كما يمكن إضافة خاصيات مخصّصةٌ في <code>separators.updateProps</code>. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
| | | (مكون component, عنصر element) | ||
|لا | | لا | ||
|} | |} | ||
===<code> | === <code>keyExtractor</code> === | ||
تُستخدم لاستخراج مفتاح فريد للعنصر المعطى وفق الدليل | |||
تُستخدم لاستخراج مفتاح فريد للعنصر المعطى وفق الدليل المحدّد، حيث يُستخدم هذا المفتاح للتّخزين المؤقّت (caching) ولتعقّب إعادة طلب العنصر، يتفحّص المستخرج الافتراضيّ <code>item.key</code> ثم يعود لاستخدام الدليل -كما يفعل React-، مع ملاحظة أن هذا المستخرج يحدّد مفاتيحًا لكلّ عنصر، ولا يزال كل قسمٍ عامٍّ بحاجةٍ لمفتاح خاصٍّ. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
| | | item: Item, index: number) => string) | ||
|نعم | | نعم | ||
|} | |} | ||
=== <code> | === <code>ListEmptyComponent</code> === | ||
تصيّر عندما تكون القائمة فارغةً، ويمكن أن يكون مكوّن [[React]] (مثل <code>SomeComponent</code>) أو عنصر React (مثل <code><SomeComponent /></code>). | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
| | | (مكون component, عنصر element) | ||
|لا | | لا | ||
|} | |} | ||
===<code> | === <code>ListFooterComponent</code> === | ||
يصيّر في آخر القائمة، ويمكن أن يكون مكوّن [[React]] (مثل <code>SomeComponent</code>) أو عنصر React (مثل <code><SomeComponent /></code>). | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
| | | (مكون component, عنصر element) | ||
|لا | | لا | ||
|} | |} | ||
===<code> | === <code>ListHeaderComponent</code> === | ||
يُصيّر في بداية القائمة، ويمكن أن يكون مكوّن [[React]] (مثل <code>SomeComponent</code>) أو عنصر React (مثل <code><SomeComponent /></code>). | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
| | | (مكون component, عنصر element) | ||
|لا | | لا | ||
|} | |} | ||
===<code> | === <code>onEndReached</code> === | ||
تُستدعى عند وصول موقع التمرير إلى | |||
تُستدعى عند وصول موقع التمرير إلى الخاصّية <code>onEndReachedThreshold</code> في المحتوى المُصيّر. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
| | | <code>(info: {distanceFromEnd: number}) => void</code> | ||
|لا | | لا | ||
|} | |} | ||
===<code> | === <code>onEndReachedThreshold</code> === | ||
تحدّد كم يجب أن يكون بعد الحافة السفلى للقائمة (بوحدات طول القائمة المرئيّ) عن نهاية المحتوى والتي سيطلق عندها رد النداء <code>onEndReached</code>، لذا ستُطلق القيمة <code>0.5</code> الاستجابة <code>onEndReached</code> عندما تكون نهاية المحتوى في حدود منتصف طول القائمة المرئيّ. | |||
القيمة الافتراضية 2. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
|عدد (number) | | عدد (number) | ||
|لا | | لا | ||
|} | |} | ||
===<code> | === <code>onRefresh</code> === | ||
تُضيف | |||
تُضيف تحكّمًا معياريًّا بالتحديث (standard RefreshControl) لوظيفة السحب للتحديث (Pull to Refresh)، كما يجب ضبط الخاصيّة <code>refreshing</code> بطريقة صحيحة، فمثلًا لإزاحة التحكم بالتحديث 100 نقطة (pt) من أعلى القائمة، نضع القيمة <code>{progressViewOffset={100</code>. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
| | | دالة | ||
|لا | | لا | ||
|} | |} | ||
===<code> | === <code>onViewableItemsChanged</code> === | ||
تُستدعى | |||
تُستدعى عند تغيّر قابلية إظهار السطور، والمعرّفة بالخاصيّة <code>viewabilityConfig</code>. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
| | | (callback: { changed: array of ViewTokens, viewableItems: array of ViewTokens }) => void | ||
|لا | | لا | ||
|} | |} | ||
=== <code>refreshing</code> === | |||
تُضبط بالقيمة <code>true</code> لانتظار البيانات الجديدة من التحديث. | |||
{| class="wikitable" | {| class="wikitable" | ||
! النوع | |||
!النوع | ! مطلوب | ||
!مطلوب | |||
|- | |- | ||
| | | (bool) | ||
| لا | |||
|لا | |||
|} | |} | ||
=== <code>removeClippedSubview</code> === | |||
<blockquote>'''تنبيه''': قد تواجهة خطأ (محتوى مفقود) في بعض الحالات، لذا لا ننصح باستعمالها إلا إن أحببت المخاطرة على مسؤوليتك.</blockquote>تُستخدم لتحسين أداء التمرير في القوائم الطويلة، مع ملاحظة إمكانية ظهور بعض العيوب أحيانًا (مثل المحتوى مفقود) لذا استخدمها على مسؤوليّتك الشخصيّة. | |||
القيمة الافتراضية <code>false</code>. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
| | | (bool) | ||
|لا | | لا | ||
|} | |} | ||
===<code> | === <code>renderSectionFooter</code> === | ||
يُصيّر أسفل كلّ قسم. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
| | | (info: { section: Section }) => element, null | ||
|لا | | لا | ||
|} | |} | ||
===<code> | === <code>renderSectionHeader</code> === | ||
يُصيّر أعلى كلّ قسمٍ، كما تثبت أعلى واجهة التمرير (<code>ScrollView</code>) افتراضيًا على منصّة iOS، يمكن مراجعة الخاصيّة <code>stickySectionHeadersEnabled</code>. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
| | | (info: { section: Section }) => element, null | ||
|لا | | لا | ||
|} | |} | ||
===<code> | === <code>SectionSeparatorComponent</code> === | ||
يُصيَّر أعلى وأسفل كلّ قسمٍ (يختلف عن المكوّن <code>ItemSeparatorComponent</code> الذي يُصيَّر بين العناصر فقط)، وهو مخصّصٌ لفصل الأقسام عن الترويسات الموجودة في الأعلى والأسفل، ولها نفس استجابة التمييز (highlight) كما هو الحال مع المكوّن <code>ItemSeparatorComponent</code>، كما يستقبل الخاصيات <code>highlighted</code> و<code>[leading/trailing][Item/Section]</code>، وأية خاصيات مخصّصة من <code>separators.updateProps</code>. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
|عنصر | | (مكون component, عنصر element) | ||
|لا | | لا | ||
|} | |} | ||
===<code> | === <code>stickySectionHeadersEnabled</code> === | ||
تثبّت ترويسة القسم أعلى الشاشة حتى تأتي الترويسة التالية وتحلّ محلّها، ومفعّلة افتراضيًّا على منصّة iOS أي قيمتها <code>true</code> بينما قيمتها الافتراضية <code>false</code> على منصة Android. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
|- | |- | ||
| | | (bool) | ||
|لا | | لا | ||
|} | |} | ||
===<code> | == التوابع == | ||
=== <code>scrollToLocation()</code> === | |||
= | <syntaxhighlight lang="javascript">scrollToLocation(params);</syntaxhighlight> | ||
يمرر إلى العنصر المحدّد بالخاصيتين <code>sectionIndex</code> و<code>itemIndex</code> (ضمن القسم)، والمتوضّع في المنطقة المرئية فمثلًا إذا كانت الخاصيّة <code>viewPosition</code> تساوي 0، فسيتوضّع العنصر في الأعلى (ويمكن أن تغطيه الترويسة الثابتة)؛ أما إذا كانت قيمتها <code>1</code> فسيتوضّع في الأسفل، وإذا كانت <code>0.5</code> فسيتوضّع في المنتصف. | |||
'''ملاحظة:''' لا يمكن التمرير لموقع خارج نافذة التصيير دون تحديد الخاصيّة <code>getItemLayout</code> أو <code>onScrollToIndexFailed</code>. | |||
{| class="wikitable" | {| class="wikitable" | ||
!الاسم | ! الاسم | ||
!النوع | ! النوع | ||
!مطلوب | ! مطلوب | ||
!الوصف | ! الوصف | ||
|- | |- | ||
| | | params | ||
|كائن (object) | | كائن (object) | ||
|نعم | | نعم | ||
|انظر في الأسفل | | انظر في الأسفل | ||
|} | |} | ||
مفاتيح الكائن <code>params</code>: | مفاتيح الكائن <code>params</code>: | ||
* <code>animated</code> (قيمة منطقية) | * <code>'animated'</code> (قيمة منطقية): تحدد فيما إذا كانت القائمة ستتحرك أثناء التمرير، وقيمتها الافتراضية <code>true</code>. | ||
* <code>itemIndex</code> (عدد) | * <code>'itemIndex'</code> (عدد): دليل العنصر الذي سيُمرر إليه داخل القسم المطلوب. | ||
* <code>sectionIndex</code> (عدد) | * <code>'sectionIndex'</code> (عدد): دليل القسم الذي يحتوي على العنصر الذي سيُمرر إليه المطلوب. | ||
* <code>viewOffset</code> (عدد) | * <code>'viewOffset'</code> (عدد): عدد ثابت من البكسلات لإزاحة الموقع النهائي المطلوب، مثلًا بالموازنة مع الترويسات المثبتة. | ||
* <code>viewPosition</code> (عدد) | * <code>'viewPosition'</code> (عدد): إذا كانت قيمتها <code>0</code> فسيتوضع العنصر المطلوب في الأعلى، وإذا كانت قيمتها <code>1</code> فسيتوضّع في الأسفل، وإن كانت <code>0.5</code> فسيتوضّع في المنتصف. | ||
=== <code>recordInteraction()</code> === | |||
<syntaxhighlight lang="javascript">recordInteraction(); </syntaxhighlight> | |||
<syntaxhighlight lang="javascript"> | يخبر القائمة بحدوث تفاعل لتقوم بإطلاق حسابات قابلية الإظهار، مثلًا إذا كانت قيمة <code>waitForInteractions</code> مساويةً <code>true</code> ولم يقم المستخدم بالتمرير، يستدعى هذا التابع عادة عند النقر على العنصر أو عند التنقّل. | ||
recordInteraction(); | |||
</syntaxhighlight>يخبر القائمة بحدوث | |||
=== <code> | === <code>flashScrollIndicators()</code> === | ||
== | <syntaxhighlight lang="javascript">flashScrollIndicators();</syntaxhighlight> | ||
يُظهر مؤشرات التمرير لحظيًّا، ويعمل على منصًة iOS فقط. | |||
== تعريفات النوع == | |||
=== <code>Section</code> === | |||
كائن معرّف للمعطيات التي ستُصير في قسمٍ معطىً. | |||
{| class="wikitable" | {| class="wikitable" | ||
!النوع | ! النوع | ||
|- | |- | ||
|أي نوع (any) | | أي نوع (any) | ||
|} | |} | ||
الخاصيات: | |||
{| class="wikitable" | {| class="wikitable" | ||
!الاسم | ! الاسم | ||
!النوع | !مطلوب | ||
!الوصف | ! النوع | ||
! الوصف | |||
|- | |- | ||
|<code>data</code> | |<code>data</code> | ||
|مصفوفة (array) | |نعم | ||
|معطيات | | مصفوفة (array) | ||
| معطيات لتصيير العناصر في القسم، وهي مصفوفة من الكائنات مثل الخاصية <code>[[ReactNative/flatlist#data|FlatList's data]]</code> | |||
|- | |- | ||
|<code> | |<code>key</code> | ||
|سلسلة نصية (string) | |لا | ||
|مفتاح اختياري لتعقب إعادة ترتيب | | سلسلة نصية (string) | ||
| مفتاح اختياري لتعقب إعادة ترتيب الأقسام، ويستخدم دليل الأقسام بشكلٍ افتراضيٍ عند عدم استخدام هذا المفتاح | |||
|- | |- | ||
|<code> | |<code>renderItem</code> | ||
| | |لا | ||
|لتحديد | | دالة (function) | ||
| لتحديد مُصيرٍ اختياريٍّ لعناصر القسم بدل المُصير الافتراضي <code>renderItem</code> | |||
|- | |- | ||
|<code> | |<code>ItemSeparatorComponent</code> | ||
| | |لا | ||
|لتحديد فاصل اختياري لعناصر القسم بدل الفاصل الافتراضي <code>ItemSeparatorComponent</code> | | عنصر، مكون (component, element) | ||
| لتحديد فاصل اختياري لعناصر القسم بدل الفاصل الافتراضي <code>ItemSeparatorComponent</code> | |||
|- | |- | ||
|<code> | |<code>keyExtractor</code> | ||
|دالة (function) | |لا | ||
|لتحديد مستخرج مفتاح اختياري للقسم بدل المستخرج الافتراضي <code>keyExtractor</code> | | دالة (function) | ||
| لتحديد مستخرج مفتاح اختياري للقسم بدل المستخرج الافتراضي <code>keyExtractor</code> | |||
|} | |} | ||
== | == مصادر == | ||
* [https://facebook.github.io/react-native/docs/sectionlist صفحة | * [https://facebook.github.io/react-native/docs/sectionlist صفحة SectionList في توثيق React Native الرسميّ] | ||
[[تصنيف:ReactNative]] | |||
[[تصنيف:React Native Component]] |
المراجعة الحالية بتاريخ 14:02، 9 أكتوبر 2021
وهي واجهةٌ عالية الأداء لتصيير القوائم المقسّمة، ومن أهمّ ميّزاتها:
- منصّةٌ متعدّدةٌ (cross-platform).
- ردود نداءٍ قابلةٌ للضبط والعرض.
- تدعم ترويسة (header) القائمة.
- تدعم تذييل (footer) القائمة.
- تدعم فاصل العنصر.
- تدعم ترويسة القسم.
- تدعم فاصل الأقسام.
- تدعم تصيير العناصر والمعطيات غير المتجانسة (Heterogeneous).
- تدعم السحب للتحديث (Pull to Refresh).
- تدعم تحميل التّمرير (Scroll loading).
يمكن استخدام واجهة أبسط مثل FlatList
عند عدم الحاجة لدعم الأقسام.
مثال
import React from "react";
import { StyleSheet, Text, View, SafeAreaView, SectionList, StatusBar } from "react-native";
const DATA = [
{
title: "Main dishes",
data: ["Pizza", "Burger", "Risotto"]
},
{
title: "Sides",
data: ["French Fries", "Onion Rings", "Fried Shrimps"]
},
{
title: "Drinks",
data: ["Water", "Coke", "Beer"]
},
{
title: "Desserts",
data: ["Cheese Cake", "Ice Cream"]
}
];
const Item = ({ title }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
const App = () => (
<SafeAreaView style={styles.container}>
<SectionList
sections={DATA}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => <Item title={item} />}
renderSectionHeader={({ section: { title } }) => (
<Text style={styles.header}>{title}</Text>
)}
/>
</SafeAreaView>
);
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: StatusBar.currentHeight,
marginHorizontal: 16
},
item: {
backgroundColor: "#f9c2ff",
padding: 20,
marginVertical: 8
},
header: {
fontSize: 32,
backgroundColor: "#fff"
},
title: {
fontSize: 24
}
});
export default App;
import React, { Component } from "react";
import { StyleSheet, Text, View, SafeAreaView, SectionList, StatusBar } from "react-native";
const DATA = [
{
title: "Main dishes",
data: ["Pizza", "Burger", "Risotto"]
},
{
title: "Sides",
data: ["French Fries", "Onion Rings", "Fried Shrimps"]
},
{
title: "Drinks",
data: ["Water", "Coke", "Beer"]
},
{
title: "Desserts",
data: ["Cheese Cake", "Ice Cream"]
}
];
const Item = ({ title }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
class App extends Component {
render() {
return (
<SafeAreaView style={styles.container}>
<SectionList
sections={DATA}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => <Item title={item} />}
renderSectionHeader={({ section: { title } }) => (
<Text style={styles.header}>{title}</Text>
)}
/>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: StatusBar.currentHeight,
marginHorizontal: 16
},
item: {
backgroundColor: "#f9c2ff",
padding: 20,
marginVertical: 8
},
header: {
fontSize: 32,
backgroundColor: "#fff"
},
title: {
fontSize: 24
}
});
export default App;
يعد هذا المكون غلافًا ملائمًا للمكوّن الأساسيّ VirtualizedList
, لذا يرث خاصّيّاته (كذلك خاصّيّات ScrollView
) مع مراعاة ما يلي:
- لا تُحفظ الحالة الداخلية عند تمرير المحتوى خارج نافذة التصيير، لذا يجب التأكد من حفظ البيانات ضمن عنصر البيانات أو في المخازن الخارجية، مثل: Flux، أو Redux، أو Relay.
- يُعَدّ هذا المكوّن من النوع الصافي
PureComponent
أي أنّه لن يُعاد تصييره عندما تبقى قيم الخاصياتProps
متساويةً سطحيًا (shallow-equal)، لذا يجب التأكد من أن كلّ ما تعتمد عليه الدّالةrenderItem
يمرّر لها كخاصّيّةٍ (مثلextraData
)، بحيث لا تحتوي على المساواة الصارمة===
بعد التحديثات، وإلا فلن تُحدّث الواجهة عند التّغيير، وهذا يتضمّن الخاصيّةdata
وحالة المكوّن الأب.
- يصيّر المحتوى بصورة غير متزامنة خارج نافذة الواجهة وذلك لتقييد الذاكرة وتأمين تمريرٍ سلسٍ، مما يعني أنه يمكن التمرير أسرع من معدّل التعبئة (fill rate) مما يؤدي لظهور محتوىً فارغٍ للحظة، وهذا عبارة عن مقايضة (tradeoff) يمكن تعديلها لتناسب احتياجات كلّ تطبيق، ونعمل على تحسينه حاليًّأ.
- تبحث القائمة -افتراضيًّا- عن الخاصيّة
key
لكل عنصر لتستخدمها مثل مفتاح React، غير أنه يمكن استخدام الخاصيّةkeyExtractor
المخصّصة على أساس بديل.
الخاصيات
موروثة من خاصيّات ScrollView
.
renderItem
المُصيّر الافتراضي لكل عنصرٍ في كلّ قسمٍ، ويمكن تجاوزها عل أساس كلّ قسم، ويجب أن تعيد عنصر React
.
النوع | مطلوب |
---|---|
دالة (function) | نعم |
تمرَّر دالة التصيير ككائن له المفاتيح التالية:
'item'
(كائن): كائن العنصر والمحدد في المفتاحdata
الخاصّ بالقسم.'index'
(عدد): دليل العنصر في القسم.'section'
(كائن): كائن القسم الكامل كما هو محدّدٌ فيsections
.'separator'
(كائن): كائن له المفاتيح التالية:'highlight'
(دالة): () => void
.'unhighlight'
(دالة): () => void
.'updateProps'
(دالة): (select, newProps) => void
.'select'
(قيمة متعدّدة): قيمها المحتملة'leading'
أو'trailing'
.'newProps'
(كائن).
sections
تمثّل البيانات الفعلية تصييرها، كما هو الحال مع الخاصيّة data
في FlatList
.
النوع | مطلوب |
---|---|
مصفوفة من النوع Section (انظر في الأسفل) | نعم |
extraData
خاصّيّةٌ تبيّن للقائمة حاجتها لإعادة التصيير (على اعتبار أنها تنفّذ PureComponent
)، وتوضع فيها المعلومات التي تحتاجها الدوال (renderItem
والترويسة والتذييل وغيرها) وهي غير موجودةٍ في الخاصية data
.
النوع | مطلوب |
---|---|
أي شيء (any) | لا |
initialNumToRender
تحدد عدد العناصر المصيّرة في الدفعة الأولى، والتي ستكون كافيةً لملء الشاشة لا أكثر، مع ملاحظة أن لن يتم استبدال عناصر الواجهة الأولى كجزء من عملية التصيير بالنوافذ (windowed rendering)، تُستبدل فيه عناصر نافذة الواجهة الحالية بعناصر النافذة التالية أثناء التمرير لتحسين الأداء)، وذلك للمحافظة على فاعلية التمرير للأعلى.
القيمة الافتراضية: 10.
النوع | مطلوب |
---|---|
عدد (number) | لا |
inverted
تقوم بعكس اتجاه التّمرير، باستخدام تحويل مقياس الرسم ذي القيمة 1-
.
القيمة الافتراضية false
.
النوع | مطلوب |
---|---|
(boolean) | لا |
ItemSeparatorComponent
يُصيّر بين العناصر ولكن لا في الأعلى أو الأسفل، ويزوَّد افتراضيًّا بالخاصيات التالية:
highlighted
section
[leading/trailing][Item/Section]
،
كما تحتوي الدالة renderItem
الخاصة بالواجهة View
على separators.highlight
، و separators.unhighlight
والمستخدمة لتحديث الخاصيّة highlighted
، كما يمكن إضافة خاصيات مخصّصةٌ في separators.updateProps
.
النوع | مطلوب |
---|---|
(مكون component, عنصر element) | لا |
keyExtractor
تُستخدم لاستخراج مفتاح فريد للعنصر المعطى وفق الدليل المحدّد، حيث يُستخدم هذا المفتاح للتّخزين المؤقّت (caching) ولتعقّب إعادة طلب العنصر، يتفحّص المستخرج الافتراضيّ item.key
ثم يعود لاستخدام الدليل -كما يفعل React-، مع ملاحظة أن هذا المستخرج يحدّد مفاتيحًا لكلّ عنصر، ولا يزال كل قسمٍ عامٍّ بحاجةٍ لمفتاح خاصٍّ.
النوع | مطلوب |
---|---|
item: Item, index: number) => string) | نعم |
ListEmptyComponent
تصيّر عندما تكون القائمة فارغةً، ويمكن أن يكون مكوّن React (مثل SomeComponent
) أو عنصر React (مثل <SomeComponent />
).
النوع | مطلوب |
---|---|
(مكون component, عنصر element) | لا |
يصيّر في آخر القائمة، ويمكن أن يكون مكوّن React (مثل SomeComponent
) أو عنصر React (مثل <SomeComponent />
).
النوع | مطلوب |
---|---|
(مكون component, عنصر element) | لا |
ListHeaderComponent
يُصيّر في بداية القائمة، ويمكن أن يكون مكوّن React (مثل SomeComponent
) أو عنصر React (مثل <SomeComponent />
).
النوع | مطلوب |
---|---|
(مكون component, عنصر element) | لا |
onEndReached
تُستدعى عند وصول موقع التمرير إلى الخاصّية onEndReachedThreshold
في المحتوى المُصيّر.
النوع | مطلوب |
---|---|
(info: {distanceFromEnd: number}) => void
|
لا |
onEndReachedThreshold
تحدّد كم يجب أن يكون بعد الحافة السفلى للقائمة (بوحدات طول القائمة المرئيّ) عن نهاية المحتوى والتي سيطلق عندها رد النداء onEndReached
، لذا ستُطلق القيمة 0.5
الاستجابة onEndReached
عندما تكون نهاية المحتوى في حدود منتصف طول القائمة المرئيّ.
القيمة الافتراضية 2.
النوع | مطلوب |
---|---|
عدد (number) | لا |
onRefresh
تُضيف تحكّمًا معياريًّا بالتحديث (standard RefreshControl) لوظيفة السحب للتحديث (Pull to Refresh)، كما يجب ضبط الخاصيّة refreshing
بطريقة صحيحة، فمثلًا لإزاحة التحكم بالتحديث 100 نقطة (pt) من أعلى القائمة، نضع القيمة {progressViewOffset={100
.
النوع | مطلوب |
---|---|
دالة | لا |
onViewableItemsChanged
تُستدعى عند تغيّر قابلية إظهار السطور، والمعرّفة بالخاصيّة viewabilityConfig
.
النوع | مطلوب |
---|---|
(callback: { changed: array of ViewTokens, viewableItems: array of ViewTokens }) => void | لا |
refreshing
تُضبط بالقيمة true
لانتظار البيانات الجديدة من التحديث.
النوع | مطلوب |
---|---|
(bool) | لا |
removeClippedSubview
تنبيه: قد تواجهة خطأ (محتوى مفقود) في بعض الحالات، لذا لا ننصح باستعمالها إلا إن أحببت المخاطرة على مسؤوليتك.
تُستخدم لتحسين أداء التمرير في القوائم الطويلة، مع ملاحظة إمكانية ظهور بعض العيوب أحيانًا (مثل المحتوى مفقود) لذا استخدمها على مسؤوليّتك الشخصيّة.
القيمة الافتراضية false
.
النوع | مطلوب |
---|---|
(bool) | لا |
يُصيّر أسفل كلّ قسم.
النوع | مطلوب |
---|---|
(info: { section: Section }) => element, null | لا |
renderSectionHeader
يُصيّر أعلى كلّ قسمٍ، كما تثبت أعلى واجهة التمرير (ScrollView
) افتراضيًا على منصّة iOS، يمكن مراجعة الخاصيّة stickySectionHeadersEnabled
.
النوع | مطلوب |
---|---|
(info: { section: Section }) => element, null | لا |
SectionSeparatorComponent
يُصيَّر أعلى وأسفل كلّ قسمٍ (يختلف عن المكوّن ItemSeparatorComponent
الذي يُصيَّر بين العناصر فقط)، وهو مخصّصٌ لفصل الأقسام عن الترويسات الموجودة في الأعلى والأسفل، ولها نفس استجابة التمييز (highlight) كما هو الحال مع المكوّن ItemSeparatorComponent
، كما يستقبل الخاصيات highlighted
و[leading/trailing][Item/Section]
، وأية خاصيات مخصّصة من separators.updateProps
.
النوع | مطلوب |
---|---|
(مكون component, عنصر element) | لا |
stickySectionHeadersEnabled
تثبّت ترويسة القسم أعلى الشاشة حتى تأتي الترويسة التالية وتحلّ محلّها، ومفعّلة افتراضيًّا على منصّة iOS أي قيمتها true
بينما قيمتها الافتراضية false
على منصة Android.
النوع | مطلوب |
---|---|
(bool) | لا |
التوابع
scrollToLocation()
scrollToLocation(params);
يمرر إلى العنصر المحدّد بالخاصيتين sectionIndex
وitemIndex
(ضمن القسم)، والمتوضّع في المنطقة المرئية فمثلًا إذا كانت الخاصيّة viewPosition
تساوي 0، فسيتوضّع العنصر في الأعلى (ويمكن أن تغطيه الترويسة الثابتة)؛ أما إذا كانت قيمتها 1
فسيتوضّع في الأسفل، وإذا كانت 0.5
فسيتوضّع في المنتصف.
ملاحظة: لا يمكن التمرير لموقع خارج نافذة التصيير دون تحديد الخاصيّة getItemLayout
أو onScrollToIndexFailed
.
الاسم | النوع | مطلوب | الوصف |
---|---|---|---|
params | كائن (object) | نعم | انظر في الأسفل |
مفاتيح الكائن params
:
'animated'
(قيمة منطقية): تحدد فيما إذا كانت القائمة ستتحرك أثناء التمرير، وقيمتها الافتراضيةtrue
.'itemIndex'
(عدد): دليل العنصر الذي سيُمرر إليه داخل القسم المطلوب.'sectionIndex'
(عدد): دليل القسم الذي يحتوي على العنصر الذي سيُمرر إليه المطلوب.'viewOffset'
(عدد): عدد ثابت من البكسلات لإزاحة الموقع النهائي المطلوب، مثلًا بالموازنة مع الترويسات المثبتة.'viewPosition'
(عدد): إذا كانت قيمتها0
فسيتوضع العنصر المطلوب في الأعلى، وإذا كانت قيمتها1
فسيتوضّع في الأسفل، وإن كانت0.5
فسيتوضّع في المنتصف.
recordInteraction()
recordInteraction();
يخبر القائمة بحدوث تفاعل لتقوم بإطلاق حسابات قابلية الإظهار، مثلًا إذا كانت قيمة waitForInteractions
مساويةً true
ولم يقم المستخدم بالتمرير، يستدعى هذا التابع عادة عند النقر على العنصر أو عند التنقّل.
flashScrollIndicators()
flashScrollIndicators();
يُظهر مؤشرات التمرير لحظيًّا، ويعمل على منصًة iOS فقط.
تعريفات النوع
Section
كائن معرّف للمعطيات التي ستُصير في قسمٍ معطىً.
النوع |
---|
أي نوع (any) |
الخاصيات:
الاسم | مطلوب | النوع | الوصف |
---|---|---|---|
data
|
نعم | مصفوفة (array) | معطيات لتصيير العناصر في القسم، وهي مصفوفة من الكائنات مثل الخاصية FlatList's data
|
key
|
لا | سلسلة نصية (string) | مفتاح اختياري لتعقب إعادة ترتيب الأقسام، ويستخدم دليل الأقسام بشكلٍ افتراضيٍ عند عدم استخدام هذا المفتاح |
renderItem
|
لا | دالة (function) | لتحديد مُصيرٍ اختياريٍّ لعناصر القسم بدل المُصير الافتراضي renderItem
|
ItemSeparatorComponent
|
لا | عنصر، مكون (component, element) | لتحديد فاصل اختياري لعناصر القسم بدل الفاصل الافتراضي ItemSeparatorComponent
|
keyExtractor
|
لا | دالة (function) | لتحديد مستخرج مفتاح اختياري للقسم بدل المستخرج الافتراضي keyExtractor
|