提交 0e166f5b authored 作者: 王绍森's avatar 王绍森

增加listView组件

上级 4655e08f
.listWrapper {
:global {
.am-list-body {
background-color: transparent;
}
.am-list-body::before, .am-list-body::after {
display: none !important;
}
}
}
import { ActivityIndicator, } from 'antd-mobile';
import styles from './LoadingComponent.less';
export default function LoadingComponent({ isLoading }) {
return (
<div className={styles.loadingWrapper}>
{
isLoading ? (
<ActivityIndicator text="加载中..." size='large' style={{justifyContent: 'center'}} />
) : "加载完毕"
}
</div>
);
}
.loadingWrapper {
text-align: center;
padding: 1em 0;
:global {
.am-activity-indicator {
justify-content: center;
}
}
}
import React, { useEffect, useState, useCallback } from 'react';
import { ListView, PullToRefresh, } from 'antd-mobile';
import LoadingComponent from './LoadingComponent';
import styles from './ListViewDiy.less';
const defaultPagination = {
pageNo: 1,
pageSize: 10,
total: 1,
hasNextPage: true,
}
// 函数式组件,有问题,不要用
// 封装的listView组件,展示分页后的数据,可以下拉刷新,滚动到底部请求数据,传递搜索条件刷新。
// props:
// request: 请求方法, params => promise 接受查询条件为参数,返回一个promise,promise.resolve()的值是接口返回的response
// renderRow: ListView组件的renderRow,
// searchValues: 搜索条件
// mountedSearch: 页面加载后是否查询
// ListSeparator: ListView组件的ListSeparator
const defaultListViewData = new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
});
export default function TasksListComponent({ request, renderRow, searchValues, mountedSearch, ListSeparator }) {
const [isLoading, toggleLoading] = useState(false);
const [refreshing, toggleRefreshing] = useState(false);
const [listViewData, setListViewData] = useState(defaultListViewData);
const [dataSource, setDataSource] = useState([]); // 用数组保存数据,复制给listViewData
const [pagination, setPagination] = useState(defaultPagination);
const queryData = useCallback(
(isRefresh = true) => {
const { hasNextPage, pageSize, pageNo, } = pagination;
if (isLoading) return;
if (!isRefresh && !hasNextPage) return;
toggleLoading(true);
if (isRefresh) {
setPagination(defaultPagination);
toggleRefreshing(true);
}
const params = {
pageNo,
pageSize,
...searchValues,
};
request(params).then(res => {
if (res) {
const { rows, pageNo, pageSize, hasNextPage, } = res;
const ds = isRefresh ? rows : dataSource.concat(rows);
setDataSource(ds);
setListViewData(listViewData.cloneWithRows(ds));
setPagination({...pagination, pageNo, pageSize, hasNextPage, });
}
}).finally(() => {
toggleLoading(false);
toggleRefreshing(false);
});
}
, [ pagination, searchValues ])
useEffect(() => {
queryData(true);
}, [queryData, mountedSearch]);
function onEndReached(event) {
const { hasNextPage } = pagination;
if (isLoading || !hasNextPage) {
return;
}
setPagination({...pagination, pageNo: pagination.pageNo + 1});
}
const { pageSize } = pagination;
return (
<div className={styles.listWrapper}>
<ListView
dataSource={listViewData}
renderFooter={() => <LoadingComponent isLoading={isLoading} /> }
renderRow={(rowData, sectionID, rowID, highlightRow) => renderRow(
rowData, sectionID, rowID, highlightRow, () => queryData(true)
)}
renderSeparator={ListSeparator}
scrollRenderAheadDistance={500}
pageSize={pageSize}
onEndReached={onEndReached}
onEndReachedThreshold={10}
pullToRefresh={<PullToRefresh
refreshing={refreshing}
onRefresh={() => setPagination(defaultPagination)}
/>}
style={{
height: '100%',
overflow: 'scroll',
}}
/>
</div>
);
}
TasksListComponent.defaultProps = {
ListSeparator: () => <></>,
}
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { ListView, PullToRefresh, } from 'antd-mobile';
import LoadingComponent from './LoadingComponent';
import styles from './ListViewDiy.less';
// 封装的listView组件,展示分页后的数据,可以下拉刷新,滚动到底部请求数据,传递搜索条件刷新。
// props:
// request: 请求方法, params => promise 接受查询条件为参数,返回一个promise,promise.resolve()的值是接口返回的response
// renderRow: ListView组件的renderRow,
// searchValues: 搜索条件
// pageSize, 每页显示多少条数据
// mountedSearch: 页面加载后是否查询
// ListSeparator: ListView组件的ListSeparator
// NoResult: 搜索结果为空时显示的内容
export class ListViewDiy extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: false, // 管理footer组件里面的loading状态, 只有滚动到底部加载数据时才为ture, 不覆盖旧数据
isRefreshing: false, // pullToRefresh组件的loading状态,只有搜索和下拉刷新时为true,覆盖旧数据
listViewData: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
dataSource: [],
height: document.documentElement.clientHeight * 3 / 4,
hasSearched: false, // 是否已经搜索过,
...this.defaultPagination(),
}
}
static LoadingMore = 'LoadingMore';
static RefreshData = 'RefreshData'
componentDidMount() {
const hei = document.documentElement.clientHeight - ReactDOM.findDOMNode(this.lv).parentNode.offsetTop;
this.setState({
height: hei,
});
if (this.props.mountedSearch) {
this.queryData();
}
}
componentDidUpdate(prevProps) {
if (prevProps.searchValues !== this.props.searchValues) {
this.queryData();
}
}
defaultPagination = () => ({
pageNo: 1,
pageSize: this.props.pageSize,
total: 1,
hasNextPage: true,
})
queryData = (isRefresh = true) => {
const { searchValues, } = this.props;
const { isLoading, isRefreshing, hasNextPage, pageSize, pageNo, } = this.state;
if (isLoading || isRefreshing || !hasNextPage) return;
// 如果是刷新数据,只改变pullToRefresh组件的loading状态,否则改变footer的loading状态
this.setState({[isRefresh ? 'isRefreshing' : 'isLoading']: true });
const params = {
pageNo: isRefresh ? 1 : pageNo,
pageSize,
...searchValues,
};
this.props.request(params).then(res => {
if (res) {
const { rows, pageNo, pageSize, hasNextPage, } = res;
this.setState(({ dataSource, listViewData, }) => {
const ds = isRefresh ? rows : dataSource.concat(rows);
return {
dataSource: ds,
listViewData: listViewData.cloneWithRows(ds),
pageNo,
pageSize,
hasNextPage,
hasSearched: true,
};
})
}
}).finally(() => {
this.setState({ isLoading: false, isRefreshing: false, });
});
}
onEndReached = (event) => {
this.setState(({ pageNo }) => ({ pageNo: pageNo + 1}), this.queryData(false));
}
render() {
const { listViewData, isLoading, isRefreshing, height, hasSearched, dataSource, } = this.state;
const { renderRow, ListSeparator, pageSize = 10, NoResult } = this.props;
const renderFooter = () => {
if (!hasSearched) return null;
if (!dataSource.length) return NoResult;
return <LoadingComponent isLoading={isLoading} />
}
return (
<div className={styles.listWrapper}>
<ListView
ref={el => this.lv = el}
dataSource={listViewData}
renderFooter={renderFooter}
renderRow={(rowData, sectionID, rowID, highlightRow) => renderRow(
rowData, sectionID, rowID, highlightRow, this.queryData,
)}
renderSeparator={ListSeparator}
scrollRenderAheadDistance={500}
onEndReached={this.onEndReached}
pullToRefresh={<PullToRefresh
refreshing={isRefreshing}
onRefresh={this.queryData}
/>}
pageSize={pageSize}
initialListSize={pageSize}
onEndReachedThreshold={10}
style={{
height,
overflow: 'scroll',
}}
/>
</div>
);
}
}
export default ListViewDiy;
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论