ホームページ >ウェブフロントエンド >jsチュートリアル >React でネイティブを使用してカスタム プルダウンを実装し、プルアップによって読み込まれたリストを更新する方法

React でネイティブを使用してカスタム プルダウンを実装し、プルアップによって読み込まれたリストを更新する方法

亚连
亚连オリジナル
2018-06-02 14:37:592631ブラウズ

この記事では、React Native でプルアップのロードされたリストを更新するためにプルダウンをカスタマイズする例を主に紹介しますので、参考として共有します。

リスト ページは、モバイル開発で非常に一般的なページです。React Native では、通常、FlatList コンポーネントまたは SectionList コンポーネントを使用してこれらのリスト ビューを実装します。通常、リスト ページにはロードして表示する必要があるデータが大量にあるため、リスト コンポーネントでは、プルダウン リフレッシュとプルアップ ロードを実装することが不可欠です。多くの場合。

この記事では、FlatList に基づいてプルダウン更新とプルアップ読み込みをサポートする RefreshListView をカプセル化します。元の FlatList をカプセル化した後、プルアップおよびプルダウン更新を呼び出すと非常に便利です。

プルダウン更新の実装は非常に簡単です。ここでは FlatList 自体のプロパティを使用して

onRefresh - このオプションを設定すると、標準の RefreshControl コントロールがリストの先頭に追加されます。 「プルダウンリフレッシュ」機能。同時に、リフレッシュ属性を正しく設定する必要があります。

refreshing—— ブール値。リフレッシュ コントロールの表示と非表示を制御するために使用されます。更新が完了したら false に設定します。

これら 2 つのプロパティを設定することで、コントロールはデフォルトのスタイルを使用して表示することができます。

重要な点は、プルアップしてさらにロードすることです。React Native のリスト コンポーネントにはこの機能がないため、自分で実装する必要があります。 プルアップ読み込みの場合、通常は複数の状態があります。ここでは、プルアップ読み込み状態を保存するための RefreshState.js ファイルを作成します。

export default {
 Idle: 'Idle',        // 初始状态,无刷新的情况
 CanLoadMore: 'CanLoadMore', // 可以加载更多,表示列表还有数据可以继续加载
 Refreshing: 'Refreshing',  // 正在刷新中
 NoMoreData: 'NoMoreData',  // 没有更多数据了
 Failure: 'Failure'     // 刷新失败
}

次に、これらの状態に基づいて RefreshFooter コンポーネントをカプセル化して、状況に応じて異なるコンテンツを表示できるようにします。

import React, {Component} from 'react';
import {View, Text, ActivityIndicator, StyleSheet, TouchableOpacity} from 'react-native';
import RefreshState from './RefreshState';
import PropTypes from 'prop-types';

export default class RefreshFooter extends Component {

 static propTypes = {
  onLoadMore: PropTypes.func,   // 加载更多数据的方法
  onRetryLoading: PropTypes.func, // 重新加载的方法
 };
 
 static defaultProps = {
  footerRefreshingText: "努力加载中",
  footerLoadMoreText: "上拉加载更多",
  footerFailureText: "点击重新加载",
  footerNoMoreDataText: "已全部加载完毕"
 };
 
 render() {
  let {state} = this.props;
  let footer = null;
  switch (state) {
   case RefreshState.Idle:
    // Idle情况下为null,不显示尾部组件
    break;
   case RefreshState.Refreshing:
    // 显示一个loading视图
    footer =
     <View style={styles.loadingView}>
      <ActivityIndicator size="small"/>
      <Text style={styles.refreshingText}>{this.props.footerRefreshingText}</Text>
     </View>;
    break;
   case RefreshState.CanLoadMore:
    // 显示上拉加载更多的文字
    footer =
     <View style={styles.loadingView}>
      <Text style={styles.footerText}>{this.props.footerLoadMoreText}</Text>
     </View>;
    break;
   case RefreshState.NoMoreData:
    // 显示没有更多数据的文字,内容可以自己修改
    footer =
     <View style={styles.loadingView}>
      <Text style={styles.footerText}>{this.props.footerNoMoreDataText}</Text>
     </View>;
    break;
   case RefreshState.Failure:
    // 加载失败的情况使用TouchableOpacity做一个可点击的组件,外部调用onRetryLoading重新加载数据
    footer =
     <TouchableOpacity style={styles.loadingView} onPress={()=>{
      this.props.onRetryLoading && this.props.onRetryLoading();
     }}>
      <Text style={styles.footerText}>{this.props.footerFailureText}</Text>
     </TouchableOpacity>;
    break;
  }
  return footer;
 }
}

const styles = StyleSheet.create({
 loadingView: {
  flexDirection: &#39;row&#39;,
  justifyContent: &#39;center&#39;,
  alignItems: &#39;center&#39;,
  padding: 15,
 },
 refreshingText: {
  fontSize: 12,
  color: "#666666",
  paddingLeft: 10,
 },
 footerText: {
  fontSize: 12,
  color: "#666666"
 }
});

propTypes は外部呼び出し用の RefreshFooter コンポーネント用に定義するメソッドであることに注意してください。メソッドのタイプは、Facebook の prop-types 依存関係ライブラリを使用して指定する必要があります。インストールするには、エラーが発生しにくい、yarn add prop-types インストールを使用するのが最善です。これは実行時の型チェックに使用されます。詳細については、ここをクリックしてください。

defaultProps では、さまざまな状態のいくつかのデフォルトのテキスト コンテンツを定義します。これらは、値を外部に渡すことで変更できます。

次のステップは、この RefreshListView を実装することです。まず、この RefreshListView にはヘッド リフレッシュとテール リフレッシュの呼び出しメソッドが必要であり、データを呼び出す特定のメソッドは外部で実装する必要があることを明確にする必要があります。まず RefreshFooter のような 2 つのメソッドを定義します。

static propTypes = {
 onHeaderRefresh: PropTypes.func, // 下拉刷新的方法,供外部调用
 onFooterRefresh: PropTypes.func, // 上拉加载的方法,供外部调用
};

前述したように、ヘッドのプルダウン更新は FlatList の組み込み機能を使用して実装されます。ブール値 isHeaderRefreshing を更新属性の値として定義する必要があります。ヘッダーが表示されるかどうか。同時に、末尾コンポーネントの更新ステータスを決定するための isFooterRefreshing を定義します。 footerState を定義して、現在の末尾コンポーネントの状態を RefreshFooter の値として設定します。

constructor(props) {
  super(props);
  this.state = {
   isHeaderRefreshing: false, // 头部是否正在刷新
   isFooterRefreshing: false, // 尾部是否正在刷新
   footerState: RefreshState.Idle, // 尾部当前的状态,默认为Idle,不显示控件
  }
 }

render 関数は次のとおりです。

render() {
  return (
   <FlatList
    {...this.props}
    onRefresh={()=>{ this.beginHeaderRefresh() }}
    refreshing={this.state.isHeaderRefreshing}
    onEndReached={() => { this.beginFooterRefresh() }}
    onEndReachedThreshold={0.1} // 这里取值0.1(0~1之间不包括0和1),可以根据实际情况调整,取值尽量小
    ListFooterComponent={this._renderFooter}
   />
  )
 }
 
 _renderFooter = () => {
  return (
   <RefreshFooter
    state={this.state.footerState}
    onRetryLoading={()=>{
     this.beginFooterRefresh()
    }}
   />
  )
 };

上記のコードでは、beginHeaderRefresh と beginFooterRefresh の 2 つのメソッドがリフレッシュの呼び出しに使用されていることがわかりますが、判断する必要がある論理的な状況がいくつかあります。リフレッシュする前に。たとえば、先頭と末尾を同時にリフレッシュすることはできません。そうしないと、リフレッシュ中に繰り返しのリフレッシュ操作が影響を受ける可能性があります。これらはすべて考慮事項です。ここでコード内で詳細にコメントしました:

/// 开始下拉刷新
beginHeaderRefresh() {
 if (this.shouldStartHeaderRefreshing()) {
  this.startHeaderRefreshing();
 }
}

/// 开始上拉加载更多
beginFooterRefresh() {
 if (this.shouldStartFooterRefreshing()) {
  this.startFooterRefreshing();
 }
}

/***
 * 当前是否可以进行下拉刷新
 * @returns {boolean}
 *
 * 如果列表尾部正在执行上拉加载,就返回false
 * 如果列表头部已经在刷新中了,就返回false
 */
shouldStartHeaderRefreshing() {
 if (this.state.footerState === RefreshState.refreshing ||
  this.state.isHeaderRefreshing ||
  this.state.isFooterRefreshing) {
  return false;
 }
 return true;
}

/***
 * 当前是否可以进行上拉加载更多
 * @returns {boolean}
 *
 * 如果底部已经在刷新,返回false
 * 如果底部状态是没有更多数据了,返回false
 * 如果头部在刷新,则返回false
 * 如果列表数据为空,则返回false(初始状态下列表是空的,这时候肯定不需要上拉加载更多,而应该执行下拉刷新)
 */
shouldStartFooterRefreshing() {
 if (this.state.footerState === RefreshState.refreshing ||
  this.state.footerState === RefreshState.NoMoreData ||
  this.props.data.length === 0 ||
  this.state.isHeaderRefreshing ||
  this.state.isFooterRefreshing) {
  return false;
 }
 return true;
}

startHeaderRefreshing と startFooterRefreshing のロジックは次のとおりです:

/// 下拉刷新,设置完刷新状态后再调用刷新方法,使页面上可以显示出加载中的UI,注意这里setState写法
startHeaderRefreshing() {
 this.setState(
  {
   isHeaderRefreshing: true
  },
  () => {
   this.props.onHeaderRefresh && this.props.onHeaderRefresh();
  }
 );
}

/// 上拉加载更多,将底部刷新状态改为正在刷新,然后调用刷新方法,页面上可以显示出加载中的UI,注意这里setState写法
startFooterRefreshing() {
 this.setState(
  {
   footerState: RefreshState.Refreshing,
   isFooterRefreshing: true
  },
  () => {
   this.props.onFooterRefresh && this.props.onFooterRefresh();
  }
 );
}

更新する前に、先頭または末尾のコンポーネントを表示してから、外部データ インターフェイス メソッドを呼び出す必要があります。ここで setState を記述する利点は、this.props.onFooterRefresh && this.props.onFooterRefresh() が外部で記述されている場合、アロー関数のメソッドが状態の値が更新された後にのみ呼び出されることです。 setState、UI では、先頭のロードや末尾のハード ロードが表示されない場合がありますが、インターフェイス メソッドはすでに呼び出されています。

最後に、更新が完了した後、先頭または末尾のコンポーネントが表示されなくなるように、更新停止メソッドを呼び出す必要もあります。そうしないと、常に読み込まれている場合はバグとみなされる可能性があります。更新を停止する方法を見てみましょう:

/**
 * 根据尾部组件状态来停止刷新
 * @param footerState
 *
 * 如果刷新完成,当前列表数据源是空的,就不显示尾部组件了。
 * 这里这样做是因为通常列表无数据时,我们会显示一个空白页,如果再显示尾部组件如"没有更多数据了"就显得很多余
 */
endRefreshing(footerState: RefreshState) {
 let footerRefreshState = footerState;
 if (this.props.data.length === 0) {
  footerRefreshState = RefreshState.Idle;
 }
 this.setState({
  footerState: footerRefreshState,
  isHeaderRefreshing: false,
  isFooterRefreshing: false
 })
}

ここで尾部コンポーネントのステータス パラメーターを渡すことは、尾部コンポーネントのスタイルを更新することです。同時に、データソースのデータが空であると判断され、現在データが存在しないことを意味するため、末尾コンポーネントを表示する必要はありません。

以下は、RefreshListView を使用して実装した、Douban ムービー ページのページ読み込みのレンダリングです。

上記は、私が皆さんのためにまとめたものです。将来、皆さんのお役に立てれば幸いです。

関連記事:

JSで実装された集合重複排除、交差集合、和集合、差分集合関数の例

setTimeout時間を0に設定詳細分析

vue-cliのスキャフォールディング設定ディレクトリindex.jsの設定ファイルメソッド

以上がReact でネイティブを使用してカスタム プルダウンを実装し、プルアップによって読み込まれたリストを更新する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。