ReactNative 의 FlatList 사용 및 구덩이 밟 기 패키지 요약
다음은 간단 한 예 를 들 어 보 겠 습 니 다.우리 문장 에 도 이런 예 가 있어 토론 을 시작 했다.
<FlatList
data={this.state.dataList} extraData={this.state}
refreshing={this.state.isRefreshing}
onRefresh={() => this._onRefresh()}
keyExtractor={(item, index) => item.id}
ItemSeparatorComponent={() => <View style={{
height: 1,
backgroundColor: '#D6D6D6'
}}/>}
renderItem={this._renderItem}
ListEmptyComponent={this.emptyComponent}/>
//
emptyComponent = () => {
return <View style={{
height: '100%',
alignItems: 'center',
justifyContent: 'center',
}}>
<Text style={{
fontSize: 16
}}> </Text>
</View>
}
위의 코드 에서 저 희 는 주로 ListEmpty Component 를 살 펴 보 겠 습 니 다.데이터 가 없 을 때 채 워 진 레이아웃 을 표시 합 니 다.일반적인 상황 에서 저 희 는 중간 에 알림 정 보 를 표시 하고 편리 함 을 위해 데이터 없 이 새로 고침 을 간단하게 보 여 줍 니 다.위의 코드 는 데이터 가 중간 에 표시 되 지 않 은 것 처럼 보이 지만 실행 한 후에 당신 은 눈 이 멀 었 습 니 다.데이터 가 맨 위 에 중간 에 표시 되 지 않 았 습 니 다.이때 높이 는 100%효과 가 없 었 습 니 다.물론 flex:1 을 사용 하여 View 의 높 은 보 기 를 남 은 전체 화면 에 채 우려 고 시 도 했 지만 효과 가 없 었 습 니 다.그런데 왜 효과 가 없 는 지 궁금 하 니까 소스 코드 를 찾 아 보 자.원본 경 로 는 react-native-->Libraries-->Lists 에 있 습 니 다.목록 의 구성 요 소 는 모두 이 디 렉 터 리 아래 에 있 습 니 다.먼저 FlatList 파일 에서 키 워드 를 검색 합 니 다.ListEmpty Component 에서 이 구성 요소 가 사용 되 지 않 았 음 을 발견 하면 render 로 계속 갑 니 다.
render() {
if (this.props.legacyImplementation) {
return (
<MetroListView
{...this.props}
items={this.props.data}
ref={this._captureRef}
/>
);
} else {
return (
<VirtualizedList
{...this.props}
renderItem={this._renderItem}
getItem={this._getItem}
getItemCount={this._getItemCount}
keyExtractor={this._keyExtractor}
ref={this._captureRef}
onViewableItemsChanged={
this.props.onViewableItemsChanged && this._onViewableItemsChanged
}
/>
);
}
}
MetroListView(내부 실행 은 ScrollView)는 낡은 ListView 실현 방식 이 고 VirtualizedList 는 새로운 성능 이 비교적 좋 은 실현 이다.우 리 는 이 서류 에 간다.
//
const itemCount = this.props.getItemCount(data);
if (itemCount > 0) {
....
} else if (ListEmptyComponent) {
const element = React.isValidElement(ListEmptyComponent)
? ListEmptyComponent // $FlowFixMe
: <ListEmptyComponent />;
cells.push(
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
* comment suppresses an error when upgrading Flow's support for React.
* To see the error delete this comment and run Flow. */
<View
key="$empty"
onLayout={this._onLayoutEmpty}
style={inversionStyle}>
{element}
</View>,
);
}
여기 서 우리 가 정의 하 는 ListEmpty Component 외 에 view 를 보 았 습 니 다.이 view 는 스타일 inversionStyle 을 추가 하 였 습 니 다.
const inversionStyle = this.props.inverted
? this.props.horizontal
? styles.horizontallyInverted
: styles.verticallyInverted
: null;
:
verticallyInverted: {
transform: [{scaleY: -1}],
},
horizontallyInverted: {
transform: [{scaleX: -1}],
},
위의 스타일 은 애니메이션 을 추가 한 것 입 니 다.높이 를 설정 하지 않 았 기 때문에 ListEmpty Component 에서 height:'100%'나 flex:1 을 사용 해도 효과 가 없고 높이 를 올 리 지 못 했 습 니 다.우리 가 원 하 는 효 과 를 실현 하기 위해 서 는 height 를 구체 적 인 값 으로 설정 해 야 합 니 다.그럼 이 값 을 얼마나 설정 해 야 하나 요?FlatList 에 스타일 을 설정 하면 배경 속성 에 색상 을 설정 합 니 다.FlatList 는 기본적으로 남 은 화면 을 차지 하 는 높이(flex:1)입 니 다.그러면 ListEmpty Component 에서 view 의 높이 를 FlatList 의 높이 로 설정 할 수 있 습 니 다.FlatList 의 높이 를 얻 으 려 면 onLayout 를 통 해 얻 을 수 있 습 니 다.
코드 조정:
//
fHeight = 0;
<FlatList
data={this.state.dataList} extraData={this.state}
refreshing={this.state.isRefreshing}
onRefresh={() => this._onRefresh()}
keyExtractor={(item, index) => item.id}
ItemSeparatorComponent={() => <View style={{
height: 1,
backgroundColor: '#D6D6D6'
}}/>}
renderItem={this._renderItem}
onLayout={e => this.fHeight = e.nativeEvent.layout.height}
ListEmptyComponent={this.emptyComponent}/>
//
emptyComponent = () => {
return <View style={{
height: this.fHeight,
alignItems: 'center',
justifyContent: 'center',
}}>
<Text style={{
fontSize: 16
}}> </Text>
</View>
}
위의 조정 을 통 해 안 드 로 이 드 에서 실 행 될 때 우리 가 원 하 는 효 과 를 거 두 었 음 을 알 수 있 습 니 다.그러나 iOS 에 서 는 제어 할 수 없고 가끔 중간 에 표시 되 며 가끔 은 맨 위 에 표 시 됩 니 다.이 유 는 iOS 에서 onLayout 호출 시기 가 Android 와 약간 다 르 기 때 문 입 니 다.그래서 변 경 된 값 을 empty Component 에 사용 하기 위해 fHeight 를 state 에 설정 합 니 다.
state={
fHeight:0
}
onLayout={e => this.setState({fHeight: e.nativeEvent.layout.height})}
이렇게 설정 하면 완벽 하 겠 죠?하지만...............................................................................인쇄 로그 의 발견 값 은 0 과 측정 후의 값 을 왔 다 갔다 합 니 다.여기 서 우 리 는 단지 측정 한 값 만 필요 하기 때문에 onLayout 를 수정 합 니 다.
onLayout={e => {
let height = e.nativeEvent.layout.height;
if (this.state.fHeight < height) {
this.setState({fHeight: height})
}
}}
처 리 를 거 친 후에 ios 에서 우리 가 원 하 는 효 과 를 완벽 하 게 실현 했다.위의 구 덩이 를 제외 하고 개인 적 으로 또 하나의 구 덩이 는 onEndReached 라 고 생각 합 니 다.만약 에 우리 가 드 롭 다운 로드 기능 을 실현 하면 모두 이 속성 을 사용 합 니 다.이 속성 을 언급 하면 우 리 는 당연히 onEndReached Threshold 를 언급 해 야 합 니 다.FlatList 에서 onEndReached Threshold 는 number 유형 입 니 다.그 는 구체 적 인 밑부분 이 얼마나 멀 었 을 때 onEndReached 를 촉발 하 는 지 표시 합 니 다.주의해 야 할 것 은 FlatList 와 ListView 의 onEndReached Threshold 가 나타 내 는 의 미 는 다 릅 니 다.ListView 에서 onEndReached Threshold 는 구체 적 인 아래쪽 에 픽 셀 이 얼마나 있 는 지 표시 할 때 onEndReached 를 터치 합 니 다.기본 값 은 1000 입 니 다.한편,FlatList 는 하나의 배수(픽 셀 이 아 닌 비율 이 라 고도 함)를 나타 내 고 기본 값 은 2 입 니 다.
그럼 관례 대로 아래 를 보면 서 이 루어 지 겠 습 니 다.
<FlatList
data={this.state.dataList}
extraData={this.state}
refreshing={this.state.isRefreshing}
onRefresh={() => this._onRefresh()}
ItemSeparatorComponent={() => <View style={{
height: 1,
backgroundColor: '#D6D6D6'
}}/>}
renderItem={this._renderItem}
ListEmptyComponent={this.emptyComponent}
onEndReached={() => this._onEndReached()}
onEndReachedThreshold={0.1}/>
그리고 저희 가 componentDid Mount 에 다음 코드 를 넣 을 게 요.
componentDidMount() {
this._onRefresh()
}
즉,첫 페이지 의 데 이 터 를 불 러 오기 시작 하고 드 롭 다운 실행 onEndReached 에 들 어가 더 많은 데 이 터 를 불 러 오고 데이터 원본 dataList 를 업데이트 하 는 것 입 니 다.완벽 해 보이 지만...........................................................................................onRefresh 로 데 이 터 를 불 러 오 는 데 시간 이 걸 립 니 다.데이터 가 요청 되 기 전에 render 방법 으로 실 행 됩 니 다.데이터 가 없 기 때문에 onEndReached 방법 으로 한 번 실 행 됩 니 다.이 때 는 두 번 의 데 이 터 를 불 러 온 셈 입 니 다.onEndReached 가 몇 번 을 실행 하 는 지 에 대해 서 는 onEndReached Threshold 의 값 을 정 해 야 합 니 다.그래서 우 리 는 반드시 onEndReached Threshold 를 신중하게 설정 해 야 합 니 다.만약 에 픽 셀 설정 으로 이해 하면 비교적 큰 숫자 로 설정 합 니 다.예 를 들 어 100,그러면 망 했 습 니 다.개인 감각 설정 0.1 이 좋 은 값 입 니 다.
위의 분석 을 통 해 개인 적 으로 FlatList 에 대해 2 차 포장 을 할 필요 가 있다 고 느 꼈 습 니 다.자신의 수요 에 따라 저 는 2 차 포장 을 했 습 니 다.
import React, {
Component,
} from 'react'
import {
FlatList,
View,
StyleSheet,
ActivityIndicator,
Text
} from 'react-native'
import PropTypes from 'prop-types';
export const FlatListState = {
IDLE: 0,
LoadMore: 1,
Refreshing: 2
};
export default class Com extends Component {
static propTypes = {
refreshing: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),
};
state = {
listHeight: 0,
}
render() {
var {ListEmptyComponent,ItemSeparatorComponent} = this.props;
var refreshing = false;
var emptyContent = null;
var separatorComponent = null
if (ListEmptyComponent) {
emptyContent = React.isValidElement(ListEmptyComponent) ? ListEmptyComponent : <ListEmptyComponent/>
} else {
emptyContent = <Text style={styles.emptyText}> </Text>;
}
if (ItemSeparatorComponent) {
separatorComponent = React.isValidElement(ItemSeparatorComponent) ? ItemSeparatorComponent :
<ItemSeparatorComponent/>
} else {
separatorComponent = <View style={{height: 1, backgroundColor: '#D6D6D6'}}/>;
}
if (typeof this.props.refreshing === "number") {
if (this.props.refreshing === FlatListState.Refreshing) {
refreshing = true
}
} else if (typeof this.props.refreshing === "boolean") {
refreshing = this.props.refreshing
} else if (typeof this.props.refreshing !== "undefined") {
refreshing = false
}
return <FlatList
{...this.props}
onLayout={(e) => {
let height = e.nativeEvent.layout.height;
if (this.state.listHeight < height) {
this.setState({listHeight: height})
}
}
}
ListFooterComponent={this.renderFooter}
onRefresh={this.onRefresh}
onEndReached={this.onEndReached}
refreshing={refreshing}
onEndReachedThreshold={this.props.onEndReachedThreshold || 0.1}
ItemSeparatorComponent={()=>separatorComponent}
keyExtractor={(item, index) => index}
ListEmptyComponent={() => <View
style={{
height: this.state.listHeight,
width: '100%',
alignItems: 'center',
justifyContent: 'center'
}}>{emptyContent}</View>}
/>
}
onRefresh = () => {
console.log("FlatList:onRefresh");
if ((typeof this.props.refreshing === "boolean" && !this.props.refreshing) ||
typeof this.props.refreshing === "number" && this.props.refreshing !== FlatListState.LoadMore &&
this.props.refreshing !== FlatListState.Refreshing
) {
this.props.onRefresh && this.props.onRefresh()
}
};
onEndReached = () => {
console.log("FlatList:onEndReached");
if (typeof this.props.refreshing === "boolean" || this.props.data.length == 0) {
return
}
if (!this.props.pageSize) {
console.warn("pageSize must be set");
return
}
if (this.props.data.length % this.props.pageSize !== 0) {
return
}
if (this.props.refreshing === FlatListState.IDLE) {
this.props.onEndReached && this.props.onEndReached()
}
};
renderFooter = () => {
let footer = null;
if (typeof this.props.refreshing !== "boolean" && this.props.refreshing === FlatListState.LoadMore) {
footer = (
<View style={styles.footerStyle}>
<ActivityIndicator size="small" color="#888888"/>
<Text style={styles.footerText}> …</Text>
</View>
)
}
return footer;
}
}
const styles = StyleSheet.create({
footerStyle: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
padding: 10,
height: 44,
},
footerText: {
fontSize: 14,
color: '#555555',
marginLeft: 7
},
emptyText: {
fontSize: 17,
color: '#666666'
}
})
proptypes 에서 저 희 는 oneOf Type 을 사용 하여 refreshing 형식 을 제한 합 니 다.ListEmpty Component 가 정의 가 있 으 면 사용자 정의 분 View 를 사용 하 는 것 입 니 다.같은 ItemSeparatorComponent 도 사용자 정의 할 수 있 습 니 다.드 롭 다운 으로 데 이 터 를 불 러 올 때 ListFooter Component 를 정의 합 니 다.사용자 가 데 이 터 를 불 러 오고 있 음 을 알려 줍 니 다.refreshing 속성 이 boolean 이 라면 드 롭 다운 로 딩 기능 이 없다 는 뜻 입 니 다.number 형식 이 라면 pageSize 를 전송 해 야 합 니 다.데이터 원본 길이 와 pageSize 의 나머지 가 0 인지,더 많은 데이터 가 있 는 지 판단 합 니 다.물론 위의 코드 도 간단 합 니 다.쉽게 알 아 볼 수 있 을 거 라 고 믿 습 니 다.다른 것 은 많이 소개 하지 않 겠 습 니 다.이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
바삭바삭하고 간단한 결제 페이지 만들기먼저 Next.js에서 프로젝트를 만듭니다. Vercel & Next.js가 매우 편하기 때문에 최근에는이 구성을 사용하고 있습니다. 그런 다음 Tailwind CSS를 넣습니다. Tailwind CSS를 사용하면 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.