3. React native 基础知识
无单位
在React Native中尺寸是没有单位的,它代表了设备独立像素
<View style={{ width: 100, height: 100, margin: 20 }}>
    <Text style={{ fontSize: 16, }}>hello</Text>
  </View>上述代码:运行在Android上时,View的长和宽被解析成了:100dp , dp就是单位,字体被解析成16sp, sp就是单位;运行在IOS上时尺寸被解析成了pt,这些单位确保了布局任何不同的dpi的手机屏幕上显示会发生改变;
FlexBox
rn上的flexBox和Web css上的flexBox工作方式是一样的,但有些地方还是有些出入的;
flexDirection: rn默认值是 "column", 而Web认为是 “row”
alignItems: rn默认值是“stretch”, Web默认是“flex-start”
flex: rn只接受一个参数, Web是接收多参数: flex: 1 1 10%; 设置可伸缩容器
Position
默认是相对定位
FlatList
FlatList 是 React Native 中用于高效渲染长列表数据的组件。它支持滚动、分页加载等功能,并且可以处理大量数据而不会导致性能问题
function Item({ title }) {  
  return (  
    <View style={styles.item}>  
      <Text style={styles.title}>{title}</Text>  
    </View>  
  );  
}  
  
const App = () => (  
  <FlatList  
    data={DATA}  
    renderItem={({ item }) => <Item title={item.title} />}  
    keyExtractor={item => item.id}  
  />  
); FlatList特点:
- 完全跨平台;
 - 支持水平布局模式;
 - 行组件显示或隐藏时可配置回调事件;
 - 支持单独的头部组件;
 - 支持单独的尾部组件;“
 - 支持自定义行间分隔线;
 - 支持下拉刷新;
 - 支持上拉加载;
 - 支持跳转到指定行(ScrollTolndex);
 
FlatList案例:
const  Demo = () => {
  const Item = ({ item } : any) => (  
    <View>  
      <Text>{item.title}</Text>  
    </View>  
  ); 
  let data = [
    { id: 1, title: 'title 1 '},
    { id: 2, title: 'title 2 '},
    { id: 3, title: 'title 3 '},
  ]
  return <View style={{ width: 100, margin: 20 }}>
    <FlatList<any> 
      data={data}
      renderItem={({ item }) => <Item item={item} />}  
      keyExtractor={item => item.id}  
    />
  </View>
}FlatList参数
data:
类型:Array
说明:定义 FlatList 的数据源。数组中的每个元素都将被渲染为列表中的一项。
renderItem:
类型:Function
说明:一个函数,用于渲染列表中的每一项。它接收一个对象参数,该对象包含 item(当前项的数据)和 index(当前项的索引)等属性。
keyExtractor:
类型:Function
说明:用于从数据项中提取一个唯一的键(key)。这个键用于优化渲染过程,帮助 React 识别哪些项是变化的,从而只重新渲染那些变化的项。如果不指定此函数,React Native 会默认抽取数据项中的 key 属性作为键,如果数据项中没有 key 属性,则使用数组下标作为键
numColumns:
类型:Number
说明:定义每行显示的元素个数。这个参数仅在非水平模式下有效(即 horizontal={false})。
columnWrapperStyle:
类型:StyleProp<ViewStyle>
说明:定义每个组件栏的包裹样式。这个参数同样仅在非水平模式下有效。
getItemLayout:
类型:Function
说明:用于为列表中的每一项提供一个布局信息对象。这个对象包含 length(项目的长度)、offset(项目的偏移量)和 index(项目的索引)等属性。提供这个信息可以帮助 FlatList 优化滚动性能
ListHeaderComponent:
类型:ReactClass | React.Element
说明:定义列表的头部组件。
ListFooterComponent:
类型:ReactClass | React.Element
说明:定义列表的尾部组件。
ItemSeparatorComponent:
类型:ReactClass
说明:定义列表项之间的分隔线组件。这个组件不会出现在第一行之前和最后一行之后。
numColumns:
类型:Number
说明:定义每行显示的元素个数。这个参数仅在非水平模式下有效(即 horizontal={false})。
columnWrapperStyle:
类型:StyleProp<ViewStyle>
说明:定义每个组件栏的包裹样式。这个参数同样仅在非水平模式下有效。
getItemLayout:
类型:Function
说明:用于为列表中的每一项提供一个布局信息对象。这个对象包含 length(项目的长度)、offset(项目的偏移量)和 index(项目的索引)等属性。提供这个信息可以帮助 FlatList 优化滚动性能。头部、尾部和分隔线
ListHeaderComponent:
类型:ReactClass | React.Element
说明:定义列表的头部组件。
ListFooterComponent:
类型:ReactClass | React.Element
说明:定义列表的尾部组件。
ItemSeparatorComponent:
类型:ReactClass
说明:定义列表项之间的分隔线组件。这个组件不会出现在第一行之前和最后一行之后。
horizontal:
类型:Boolean
说明:如果为 true,则列表水平滚动;如果为 false(默认值),则列表垂直滚动。
initialNumToRender:
类型:Number
说明:指定一开始渲染的元素数量。为了在最短的时间内给用户呈现可见的内容,这个数量通常设置为刚好填满一屏。
initialScrollIndex:
类型:Number
说明:设置列表一开始滚动到的位置(基于0的索引)。这个属性会关闭对“滚动到顶端”这个动作的优化。
onEndReached:
类型:Function
说明:当列表被滚动到距离内容最底部不足 onEndReachedThreshold 的距离时调用此函数。
onEndReachedThreshold:
类型:Number
说明:决定当距离内容最底部还有多远时触发 onEndReached 回调。这个参数是一个比值而非像素单位,例如 0.5 表示距离内容最底部的距离为当前列表可见长度的一半时触发。
refreshControl:
类型:React.Element<RefreshControl>
说明:如果设置了此项,则会在列表的头部添加一个标准的 RefreshControl 控件,实现下拉刷新的功能。
refreshing:
类型:Boolean
说明:是否处于刷新状态。在等待加载新数据时,将其设置为 true,列表就会显示一个正在加载的符号;加载完成后设置为 false。
onRefresh
类型:Function
说明:可选。当触发下拉刷新时调用的函数
extraData:
类型:Any
说明:如果列表的渲染依赖于某些在 data 之外的数据,可以将其放在 extraData 中。这样,当这些数据变化时,FlatList 将会重新渲染。
viewabilityConfig:
类型:Object
说明:用于配置可见性判断的参数,包括 itemVisiblePercentThreshold(项目可见百分比阈值)等。
onViewableItemsChanged:
类型:Function
说明:当可见范围的项目发生变化时调用此函数。
removeClippedSubviews(已弃用):
类型:Boolean
说明:在较旧的版本中用于优化内存使用,但已被弃用,因为 React Native 提供了更现代的内存管理策略。
VirtualizedList
VirtualizedList 是 React Native 中的一个高级组件,用于高效地渲染长列表数据。它通过在内存中只保留可见区域附近的元素(即“窗口化”)来优化性能和内存使用,这对于处理大量数据(如数百或数千个条目)的列表特别有用。VirtualizedList 是很多其他列表组件(如 FlatList 和 SectionList)的基础
const Item = ({ item }) => (  
  <View style={styles.item}>  
    <Text>{item.title}</Text>  
  </View>  
);  
  
const App = () => {  
  return (  
    <VirtualizedList  
      data={DATA}  
      renderItem={({ item }) => <Item item={item} />}  
      keyExtractor={item => item.id}  
      ItemSeparatorComponent={() => <View style={styles.separator} />}  
    />  
  );  
};  VirtualizedList有以下特性:
- 支持滚动加载(具体可以借助onEndReached的回调,做数据动态加载);
 - 支持下拉刷新(借助onRefresh / refreshing属性实现);
 - 支持可配置的可见性(VPV)回调(借助onViewableltemsChanged/ viewabilityConfig实现)
 - 滑动方向增加对Horizontal(水平)方向的支持;
 - 更加智能的Item以及section separators支持;
 - 支持Multi-column(借助numColumns属性实现);
 - 添加scrollToEnd, scrollTolndex,和 scrollToltem方法的支持;
 - 对 Flow更加友好;
 
性能
VirtualizedList除了简化API之外,新的列表组件还具有显着的性能增强,主要的是对于任意数量的行(tem)的增加不会带着内存的增加。它主要是通过虚拟元素也就是在渲染窗口之外的元素将会被从组件结构上卸载以达到回收内存目的。这样会带来一个问题,即内部组件状态不会被保留,因此请确保你跟踪组件本身以外的任何重要状态,例如,在Relay或Redux或Flux store。
限制渲染窗口还可以减少React和本地平台的工作量,例如View遍历。即使你渲染了最后的一百万个元素,用这些新的列表也不需要渲染所有的元素来完成遍历。比如:你可以使用scrolTolndex跳至中间位置,而无需过多渲染。
另外VirtualizedList还对调度进行了一些改进,这对应用程序的响应很有帮助。在任何手势或动画或其他交互完成后,呈现在窗口边缘的Item不会被频繁的渲染,并且渲染优先级比较低。
高级使用
与ListView不同的是,渲染窗口中的所有Item在任何props改变时都会重新渲染,这在通常情况下是比较好的,因为渲染窗口的Item数量是不变的,但是如果Item比较复杂的话,你因该应确保遵循React最佳性能实践,并在适当情况下使用React.PureComponent和/或shouldComponentUpdate来限制你的组件以及子组件的渲染次数,减少不必要的渲染以及递归渲染等。
如果你不需要渲染就知道内容的高度的话,可以通过getltemLayout 属性来改善用户体验,这使得通过例如滚动到具体Item更平滑。比如使用 scrollTolridex滚动到指定的Item。
如果你有另一种数据类型比如immutable的list,那么使用 VirtualizedList 是个不错的选择.它提供一个getltem属性来让你为任何给定的index返回item数据。
注意事项
当某行滑出渲染区域之外后,其内部状态将不会保留。请确保你在行组件以外的地方保留了数据。
本组件继承自PureComponent而非通常的Component,这意味着如果其props在浅比较中是相等的,则不会重新渲染。所以请先检查你的renderltem函数所依赖的props数据(包括data属性以及可能用到的父组件的state),如果是一个引用类型(Object或者数组都是引用类型),则需要先修改其引用地址(比如先复制到一个新的Object或者数组中),然后再修改其值,否则界面很可能不会刷新。(译注:这一段不了解的朋友建议先学习下is中的基本类型和引用类型。)
为了优化内存占用同时保持滑动的流畅,列表内容会在屏幕外异步绘制。这意味着如果用户滑动的速度超过渲染的速度,则会先看到空白的内容。这是为了优化不得不作出的妥协,而我们也在设法持续改进。
默认情况下每行都需要提供一个不重复的key属性。你也可以提供一个keyExtractor函数来生成key。
另外如果你有一些特殊的需求或用例,你也通过调整一些参数来实现。例如,你可以使用windowSize来平衡内存使用情況与用户体验,使用maxToRenderPerBatch调整填充率与响应度,使用onEndReachedThreshold以控制何时发生滚动加载等等。
SectionList
SectionList 是 React Native 提供的一个组件,用于显示有分区的列表。它类似于 FlatList,但 SectionList 允许你将数据组织成多个分区(section),每个分区可以有自己的头部(header)和尾部(footer),并且可以独立地进行渲染和滚动。这使得它在处理包含多个类别或分组的数据时非常有用
使用场景
- 当你有一组数据,这些数据可以被自然地分成几个部分或类别时,比如联系人列表按字母分组,或者商品列表按类型分组。
 - 当你需要在每个分区前后添加自定义的头部或尾部视图时。
 - 当你需要高效地渲染大量数据时,因为 SectionList 提供了类似于 FlatList 的性能优化。
 
基本用法
- sections:一个包含分区数据的数组。每个分区对象至少包含 data(分区内的数据数组)和 key(用于唯一标识分区的键)。
 - renderItem:一个函数,用于渲染分区内的每一项。它接收一个对象,该对象包含 item(当前项的数据)和 index(当前项的索引)等属性。
 - renderSectionHeader(可选):一个函数,用于渲染每个分区的头部。它接收一个对象,该对象包含 section(当前分区的数据)和 section: {index, key}(当前分区的索引和键)等属性。
 - renderSectionFooter(可选):一个函数,用于渲染每个分区的尾部。用法与 renderSectionHeader 类似。
 - keyExtractor:一个函数,用于从数据项中提取一个唯一的键,用于优化渲染过程
 
案例:
import React from 'react';  
import { SectionList, Text, View, StyleSheet } from 'react-native';  
  
const App = () => {  
  const sections = [  
    {  
      title: 'A',  
      data: ['Alice', 'Adam'],  
    },  
    {  
      title: 'B',  
      data: ['Bob', 'Bella'],  
    },  
    // 更多分区...  
  ];  
  
  const renderItem = ({ item }) => (  
    <View style={styles.item}>  
      <Text>{item}</Text>  
    </View>  
  );  
  
  const renderSectionHeader = ({ section: { title } }) => (  
    <View style={styles.header}>  
      <Text>{title}</Text>  
    </View>  
  );  
  
  return (  
    <SectionList  
      sections={sections}  
      renderItem={renderItem}  
      renderSectionHeader={renderSectionHeader}  
      keyExtractor={(item, index) => item} // 注意:这里需要确保key的唯一性,实际使用中可能需要更复杂的逻辑  
    />  
  );  
};  
  
const styles = StyleSheet.create({  
  header: {  
    fontSize: 20,  
    fontWeight: 'bold',  
    padding: 10,  
  },  
  item: {  
    padding: 10,  
    fontSize: 16,  
    backgroundColor: '#f9c2ff',  
  },  
});  
  
export default App;