这个插件给我最大的体会是,官网看不懂的,把官网的例子复制到自己项目中,然后修改成自己的代码,慢慢来就懂了。。。。

首先解释一下官网例1:自定义容器中各参数和方法的作用

MyBody():这个方法用于自定义滚动的范围。是整个body滚动?还是在你自定义的层里面滚动?(个人认为可以用css的相对定位,绝对定位,overflow来实现同样的效果,所以这个方法看喜好来。);

变量data:循环展示的数据集。(如果你的数据是从接口请求的数据,那么这个变量没什么用,与其关系对应的是请求的所有数据的拼接。比如请求一次:data就是这一次的数据集合;请求两次:data就是这两次请求数据的拼接集合);

变量NUM_SECTIONS:每一次加载更多显示几节。(视情况来,我的项目只是单纯的没有层级的列表,不需要这个);

变量NUM_ROWS_PER_SECTION:每一节显示多少行;

变量pageIndex :当前页码。

dataBlobs:所有数据的json集合。它这里json的key和value是一样的,格式为{'row1':row1,'row2':row2};

sectionIDs:所有节的index数组。(视情况来,我的项目只是单纯的没有层级的列表,不需要这个);

rowIDs:所有显示的行index数组;

genData():这个方法是生成DataSource中(cloneWithRowsAndSections, cloneWithRows)方法里面的参数,也就是(dataBlobs,sectionIDs,rowIDs)(如果你是接口请求的数据,绝大多数情况下不需要这个方法);

render中的const row变量:根据dataBlobs或者rowID这个二维数组的总长度来不停的循环data,直到循环完为止。简而言之,这个变量就是一个for循环;(如果是接口请求来的数据,应该循环接口返回数据的length);

if (index < 0) {
   index = data.length - 1;
}
const obj = data[index--];

这时,这部分的data对应接口请求过来的总data拼接集合

constructor,componentDidMount:照抄

// If you use redux, the data maybe at props, you need use `componentWillReceiveProps`:
这个注释部分在我的例子中会用到

onEndReached:底部加载更多的方法

---------------------------------------------------------------------------------------------------------------------------------------------------

以上我自己是懂的,但是写出来自己也有点看不太懂,但是已经非常尽量的在组织语言了。
下面附上我自己的代码图,如果有不懂或者需要附上redux部分代码的,欢迎评论,嘻嘻。

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { actionCreators } from './store';
import { ListView } from 'antd-mobile';

class StudentShare extends Component{
	
	constructor(props) {
	  super(props);
	
	  const dataSource = new ListView.DataSource({
	    rowHasChanged: (row1, row2) => row1 !== row2,
	  });
	
	  this.state = {
	    dataSource,
	    height: document.documentElement.clientHeight - (document.documentElement.clientWidth*74/375),
		};
	}
	
	 // If you use redux, the data maybe at props, you need use `componentWillReceiveProps`
	componentWillReceiveProps(nextProps) {
			
	   if (nextProps.listDataArr.toJS() !== this.props.listDataArr.toJS()) {
				// console.log(nextProps.listDataArr.toJS())
	     this.setState({
	       dataSource: this.state.dataSource.cloneWithRows(nextProps.listDataArr.toJS()),
	     });
	   }
	 }
	 
	componentDidMount(){
		this.props.getAllList(this.props.listDataNone, 1, this.props.setPageSize);
	}
	
	render() {
		const { fromPath, setPageSize, listType, pageIndex, listDataArr, isLoading, hasMore, onEndReached } = this.props;
		let isNoList = listDataArr.toJS().length === 0 ? true : false;
		let listLen = listDataArr.toJS().length;
		let listDataObj =  listDataArr.toJS();
		let index = 0;
		const row = (rowData, sectionID, rowID) => {
		  if (index > listLen) {
		    index = 0;
		  }
		  const obj = listDataObj[index++];
		  return (			
				<div key={rowID} className="item red">
					<div className="imginfo">
						<div className="label">倾情推荐</div>
					</div>
					<div className="rinfo">
						<div className="title" dangerouslySetInnerHTML={{__html:obj.classTitle}}/>
						<div className="desc" dangerouslySetInnerHTML={{__html:obj.introduce}}/>
						<div className="comlabelgroup">
							<span className="combblabel">名师分享</span>
							<span className="comrrlabel">倾情推荐</span>
						</div>
						<div className="iconinfo clear">
							{/* 
							<span className="fl icon_eye">2019</span>
							<span className="fl icon_thumb">2019</span>
							 */}
							<span className="fr watch" onClick={ev => this.props.goVideo(obj.classId, this.props.history)}>立即观看</span>
						</div>
						<div className="price">免费</div>
					</div>
				</div>
		  );
		};
		return(
			<div>
				<div className="comlistpart m20b">
					{isNoList ? (
						<NoList/>
					) : (
						<div>
							<ListView
								ref={el => this.lv = el}
								dataSource={this.state.dataSource}
								renderFooter={() => (<div style={{ padding: 10, textAlign: 'center' }}>
									{
										hasMore ? (
											isLoading ? 'Loading...' : 'Loaded'
										) : '没有更多啦!'
									}										
								</div>)}
								renderRow={row}
								style={{
									height: this.state.height,
									overflow: 'auto',
								}}
								pageSize={5}
								// onScroll={() => { console.log('scroll'); }}
								scrollRenderAheadDistance={500}
								onEndReached={ev => onEndReached(pageIndex, setPageSize, hasMore, listDataArr)}
								onEndReachedThreshold={10}
							/>
						</div>
					)}
				</div>
			</div>
		)
	}
}

const mapStateToProps = (state) => {
	return {
		setPageSize: state.getIn(['kbstudent', 'setPageSize']),
		pageIndex: state.getIn(['kbstudent', 'pageIndex']),
		isLoading: state.getIn(['kbstudent', 'isLoading']),
		hasMore: state.getIn(['kbstudent', 'hasMore']),
		listData: state.getIn(['kbstudent', 'listData']),
		listDataArr: state.getIn(['kbstudent', 'listDataArr']),
		listDataNone: state.getIn(['kbstudent', 'listDataNone']),
	}
}

const mapDispatchToProps = (dispatch) => {
	return {
		setFromPath(path){
			dispatch(actionCreators.setFromPath(path));
		},
		getAllList(listDataArr, page, pagesize){
			dispatch(actionCreators.getAllList(listDataArr, page, pagesize));
		},
		goVideo(pId, history){
			let id = parseInt(pId);
			history.push({ pathname:'/video/'+id,state:{formPath: '/studentshare'}});
		},
		onEndReached(page, setPageSize, hasMore, listDataArr) {
		  // load new data
		  // hasMore: from backend data, indicates whether it is the last page, here is false
			if (!hasMore) {
		    	return;
		  	}
			dispatch(actionCreators.changeLoading(true));
			dispatch(actionCreators.changePage(page+1));
			setTimeout(() => {
				dispatch(actionCreators.getAllList(listDataArr, page+1, setPageSize));
			}, 1000);
		},
	}
}

export default connect(mapStateToProps, mapDispatchToProps)(StudentShare);

注意点,listData是每一次请求的数据,listDataArr是多次请求的数据集合,listDataNone是空数组
踩坑,我用了immutable。之前,componentWillReceiveProps这个方法的数据没有用toJS方法,页面一直有重复数据,所以,用了immutable就一定要用toJS来转化下数据,!!!!!!!强调。

 

 

redux部分-reducer

import { fromJS } from 'immutable';
import * as constants from './constants';

const defaultState = fromJS({
	fromPath: '/',
	listData: [],
	listDataArr: [],
	listDataNone: [],
	listType: 2,
	pageIndex: 1,
	setPageSize: 10,
	isLoading: false,
	hasMore: true,
})

export default ( state = defaultState, action ) => {
	switch(action.type) {
		case constants.SET_FROMPATH:
			return state.set('fromPath', action.value);
		case constants.CHANGE_ALL_LIST:
			return state.merge({
				'listData': fromJS(action.data),
				'listDataArr': fromJS(action.plist),
			});
		case constants.CHANGE_LOADING:
			return state.set('isLoading', action.isShow);
		case constants.CHANGE_PAGE:
			return state.set('pageIndex', action.value);
		case constants.CHANGE_HASMORE:
			return state.set('hasMore', action.isShow);
		default:
			return state;
	}
}

redux部分-constants

export const SET_FROMPATH = 'kbstudent/SET_FROMPATH';
export const CHANGE_ALL_LIST = 'kbstudent/CHANGE_ALL_LIST';
export const CHANGE_LOADING = 'kbstudent/CHANGE_LOADING';
export const CHANGE_PAGE = 'kbstudent/CHANGE_PAGE';
export const CHANGE_HASMORE = 'kbstudent/CHANGE_HASMORE';

redux部分-actionCreators

import * as constants from './constants';
import abbr from '../../../../config/abbr';
import { apiGetFameShare } from '../../../../config/index';

export const getAllList = (list, pflag, ptype, ppage, ppagesize) => {
	let flag = parseInt(pflag);
	let type = parseInt(ptype);
	let page = parseInt(ppage);
	let pagesize = parseInt(ppagesize);
	let formData = {
		flag: flag,
		type: type,
		page: page,
		pagesize: pagesize,
	}
	return (dispatch) => {
		//获取全部热门课程
		apiGetFameShare(formData).then(response => {
			if (response.code === abbr.okId) {
				let plist = list.toJS().concat(response.data);
				if(plist.length >= response.total){
					dispatch(changeHasmore(false));
				}
				dispatch(changeAllList(response.data, plist));
				dispatch(changeLoading(false));
			}else{
				dispatch(changeAllList([],[]));
				dispatch(changeLoading(false));
				dispatch(changeHasmore(false));
				return;
			}
		}).catch(error => {
			dispatch(changeAllList([],[]));
			dispatch(changeLoading(false));
			dispatch(changeHasmore(false));
			console.log(error)
		})
	}
}

export const changeAllList = (data, plist) => ({
	type: constants.CHANGE_ALL_LIST,
	data, plist
})

export const changeLoading = (isShow) => ({
	type: constants.CHANGE_LOADING,
	isShow
})

export const changePage = (value) => ({
	type: constants.CHANGE_PAGE,
	value
})

export const changeHasmore = (isShow) => ({
	type: constants.CHANGE_HASMORE,
	isShow
})


export const setFromPath = (value) => ({
	type: constants.SET_FROMPATH,
	value
})