ReactNative/sectionlist

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

SectionList

وهي واجهة عالية الأداء مستخدمة لإظهار القوائم المقسمة, وتمتاز بما يلي:

  • دعم كامل للمنصات المتعددة (cross-platform).
  • تدعم ضبط استجابات الإظهار.
  • تدعم تذييل (footer) القائمة.
  • تدعم فاصل العناصر.
  • تدعم ترويسة القسم.
  • تدعم فاصل الأقسام.
  • تدعم إظهار العناصر والمعطيات الغير متجانسة (Heterogeneous).
  • تدعم السحب للتحديث (Pull to Refresh).
  • تدعم تحميل التمرير (Scroll loading).

يمكن استخدام واجهة أبسط مثل FlatList عند عدم الحاجة لدعم الأقسام.

مثال

  • مثال لمكوِّن دالّي (Function Component)
import React from "react";
import {
  StyleSheet,
  Text,
  View,
  SafeAreaView,
  SectionList
} from "react-native";
import Constants from "expo-constants";

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,
    marginTop: Constants.statusBarHeight,
    marginHorizontal: 16
  },
  item: {
    backgroundColor: "#f9c2ff",
    padding: 20,
    marginVertical: 8
  },
  header: {
    fontSize: 32,
    backgroundColor: "#fff"
  },
  title: {
    fontSize: 24
  }
});

export default App;
  • مثال لمكوِّن صنفي (Class Component)
import React, { Component } from "react";
import {
  StyleSheet,
  Text,
  View,
  SafeAreaView,
  SectionList
} from "react-native";
import Constants from "expo-constants";

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"]
  }
];

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,
    marginTop: Constants.statusBarHeight,
    marginHorizontal: 16
  },
  item: {
    backgroundColor: "#f9c2ff",
    padding: 20,
    marginVertical: 8
  },
  header: {
    fontSize: 32,
    backgroundColor: "#fff"
  },
  title: {
    fontSize: 24
  }
});

export default App;

يعد هذا المكون تغليف ملائمة (convenience wrapper) حول المكون الأساسي VirtualizedList, لذا فإن خاصياته موروثة منه (كذلك من المكوّن ScrollView) مع مراعاة ما يلي:

  • إن الحالة الداخلية غير محفوظة عند تمرير المحتوى خارج نافذة الإظهار, لذا يجب التأكد من حفظ البيانات ضمن عنصر البيانات أو في المخازن الخارجية مثل Flux أو Redux أو Relay.
  • إن هذا المكوّن من النوع الصافي PureComponent, مما يعني أنه لن يتم تحديث الإظهار في حال بقيت قيمة الخاصيات مساوية سطحيًا (shallow-equal) لقيمها السابقة. لذا يجب التأكد من أن كل شيء يتم تمريره كخاصيّة للدالة renderItem لا يحتوي على المساواة السطحية === بعد التحديثات, وإلا فإن الواجهة لن تُحدّث أثناء التغيير. ويتضمن هذا الخاصيّة data ومكوّن الحالة الأب.
  • يظهر المحتوى بشكل غير متزامن خارج نافذة الإظهار, وذلك لتقييد الذاكرة ولتأمين سلاسة في التمرير. مما يعني أنه يمكن التمرير أسرع من معدّل التعبئة (fill rate) مما يؤدي لظهور محتوى فارغ لحظيًا. وهذا عبارة عن مقايضة (tradeoff) يمكن تعديلها لتناسب احتياجات كل تطبيق.
  • تبحث القائمة بشكل افتراضي عن الخاصيّة key ضمن كل عنصر لتستخدمها كمفتاح React, غير أنه يمكن بشكل بديل استخدام الخاصيّة keyExtractor لإدخال مفتاح شخصي.

الخاصيّات (Props)

موروثة من الخاصيّات ScrollView.

renderItem

المُظهِر الافتراضي لكل عنصر في كل قسم, وهذا المظهر هو عبارة عن دالة تعيد عنصر React.

النوع مطلوب
كائن (object) لا

يُمرَّر لدالة الإظهار كائن مع المفاتيح التالية:

  • item (كائن) - كائن العنصر والمحدد في data الخاصة بالقسم.
  • index (عدد) - دليل العنصر داخل القسم.
  • section (كائن) - كائن القسم الكامل والمحدد في sections.
  • separator (كائن) - كائن له المفاتيح التالية:
    • highlight (دالة) - () => void.
    • unhighlight (دالة) - () => void.
    • updateProps (دالة) - (select, newProps) => void.
      • select (قيمة اسمية) - قيمها المحتملة leading أو trailing.
      • newProps (كائن).

sections

تمثّل البيانات الفعلية للإظهار, كما هو الحال مع الخاصيّة data في FlatList.

النوع مطلوب
مصفوفة من الأقسام (array of sections) نعم

extraData

تتضمن البيانات الإضافية التي تحتاجها دوال الإظهار (renderItem والترويسة والتذييل وغيرها) والغير موجودة في data.

النوع مطلوب
أي شيء (any) لا

initialNumToRender

تحدد عدد العناصر الواجب إظهارها في الدفعة الأولى لتملأ الشاشة لا أكثر.

ملاحظة: لن يتم استبدال عناصر الإظهار الأولى في الإظهار بالنوافذ (يتم فيه استبدال عناصر نافذة الإظهار الحالية بعناصر النافذة التالية أثناء التمرير وذلك لتحسين الأداء), وذلك للمحافظة على فاعلية التمرير للأعلى.  

النوع مطلوب
عدد (number) لا

inverted

تعكس اتجاه التمرير باستخدام تحويل مقياس الرسم ذي القيمة 1-

النوع مطلوب
قيمة منطقية (boolean) لا

ItemSeparatorComponent

يُظهَر هذا المكوّن بين العناصر ولكن ليس في الأعلى أو الأسفل, ويزوَّد بشكل افتراضي بالخاصيات highlighted و section و [leading/trailing][Item/Section]. كما تتضمن دالة الإظهار renderItem على separators.highlight و separators.unhighlight والمستخدمة لتحديث الخاصيّة highlighted, غير أنه من الممكن إضافة خاصيات شخصية مع separators. updateProps.

النوع مطلوب
عنصر, دالة, مكون (component, function, element) لا

keyExtractor

تُستخدم لاستخراج مفتاح فريد للعنصر المعطى وفق الدليل المحدد, حيث يُستخدم هذا المفتاح من أجل التخزين المؤقت (caching) ومن أجل تعقّب إعادة ترتيب العنصر. يتفحّص المستخرج الافتراضي item.key ثم يعود لاستخدام الدليل, بشكل مماثل لتوثيق React.

ملاحظة: يضع هذا المستخرج مفتاح لكل عنصر, غير أن كل قسم كامل مازال بحاجة لمفتاحه الخاص.

النوع مطلوب
سلسلة نصية ((item: Item, index: number) => string) نعم

ListEmptyComponent

يُظهَر هذا المكوّن عندما تكون القائمة فارغة, ويمكن أن يكون صنف مكوّن React أو دالة إظهار أو العنصر المُظهَر.

النوع مطلوب
عنصر, دالة, مكون (component, function, element) لا

ListFooterComponent

يُظهَر هذا المكوّن في آخر القائمة, ويمكن أن يكون صنف مكوّن React أو دالة إظهار أو العنصر المُظهَر.

النوع مطلوب
عنصر, دالة, مكون (component, function, element) لا

ListHeaderComponent

يُظهَر هذا المكوّن في بداية القائمة, ويمكن أن يكون صنف مكوّن React أو دالة إظهار أو العنصر المُظهَر.

النوع مطلوب
عنصر, دالة, مكون (component, function, element) لا

onEndReached

تُستدعى عند وصول موقع التمرير إلى العتبة onEndReachedThreshold في المحتوى المُظهَر.

النوع مطلوب
معلومات ((info: {distanceFromEnd: number}) => void) لا

onEndReachedThreshold

تحدد مسافة أسفل المحتوى المرئي عن أسفل القائمة نسبة إلى طول القسم المرئي من القائمة والتي يجب عندها إطلاق الاستجابة onEndReached, لذا ستُطلق القيمة 0.5 الاستجابة onEndReached عندما تصبح نهاية المحتوى الظاهر ضمن منتصف الطول المرئي من القائمة.

النوع مطلوب
عدد (number) لا

onRefresh

تُضيف التحكم بالتحديث المعياري (standard RefreshControl) لوظيفة السحب للتحديث (Pull to Refresh), كما يجب ضبط الخاصيّة refreshing بشكل صحيح. فمثلا توضع القيمة progressViewOffset={100} لجعل إزاحة التحكم بالتحديث 100 نقطة (pt) من أعلى القائمة.

النوع مطلوب
[() => void] لا

onViewableItemsChanged

تُستدعى هذه الدالة عند تغيّر قابلية إظهار السطور والمعرّفة بالخاصيّة viewabilityConfig.

النوع مطلوب
دالة (function) لا

يُمرر لهذه الدالة كائن له المفاتيح التالية:

  • viewableItems (مصفوفة من ViewToken)
  • changed (مصفوفة من ViewToken)

يُصدَّر النوع ViewToken عن طريق ViewabilityHelper.js:

الاسم النوع مطلوب
item أي نوع (any) نعم
key سلسلة نصية (string) نعم
index عدد (number) لا
isViewable قيمة منطقية (boolean) نعم
section أي نوع (any) لا

refreshing

تُضبط بالقيمة true لانتظار البيانات الجديدة من أجل التحديث.

النوع مطلوب
قيمة منطقية (bool) لا

removeClippedSubview

تُستخدم لتحسين أداء التمرير في القوائم الطويلة.

تنبيه: تظهر فيها أحيانًا بعض العيوب مثل المحتوى مفقود, لذا استخدمها على مسؤوليتك الشخصية.

النوع مطلوب
قيمة منطقية (bool) لا

renderSectionFooters

يُظهَر أسفل كل قسم.

النوع مطلوب
عنصر ((info: {section: SectionT}) => ?React.Element<any>) لا

renderSectionHeader

يُظهَر أعلى كل قسم. كما تلتصق بأعلى عرض التمرير (ScrollView) بشكل افتراضي على منصّة iOS, انظر الخاصيّة stickySectionHeadersEnabled.

النوع مطلوب
عنصر ((info: {section: SectionT}) => ?React.Element<any>) لا

SectionSeparatorComponent

يُظهَر هذا المكوّن في أعلى وأسفل كل قسم (يختلف عن المكوّن ItemSeparatorComponent الذي يُظهَر بين العناصر فقط), ومخصص لفصل الأقسام عن الترويسات التي في الأعلى والأسفل, ولها نفس استجابة الإبراز (highlight) كما هو الحال مع المكوّن ItemSeparatorComponent. كما يستقبل الخاصيات highlighted و [leading/trailing][Item/Section], وأية خاصيات شخصية من separators. updateProps.

النوع مطلوب
صنف React لا

stickySectionHeadersEnabled

تجعل ترويسة القسم تلتصق بأعلى الشاشة حتى تأتي الترويسة التالية وتزيحها, ومفعّلة بشكل افتراضي على منصّة iOS.

النوع مطلوب
قيمة منطقية (bool) لا

التوابع (Methods)

()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 فقط.

تعريفات النوع (Type Definitions)

Section

كائن معرّف للمعطيات التي ستُظهَر في القسم.

النوع
أي نوع (any)

الخصائص (Properties)

الاسم النوع الوصف
data مصفوفة (array) معطيات لإظهار العناصر في القسم, وهي مصفوفة من الكائنات مثل الخاصية FlatList's data prop
[key] سلسلة نصية (string) مفتاح اختياري لتعقب إعادة ترتيب الأقسام, ويستخدم دليل الأقسام بشكل افتراضي عند عدم استخدام هذا المفتاح
[renderItem] عنصر, دالة, مكون (component, function, element) لتحديد مُظهر اختياري لعناصر القسم بدل المُظهر الافتراضي renderItem
[ItemSeparatorComponent] قيمة منطقية (boolean) لتحديد فاصل اختياري لعناصر القسم بدل الفاصل الافتراضي ItemSeparatorComponent
[keyExtractor] دالة (function) لتحديد مستخرج مفتاح اختياري للقسم بدل المستخرج الافتراضي keyExtractor

مصادر