antd-mobile之listview結合react-redux的使用,帶例子,帶圖

這個插件給我最大的體會是,官網看不懂的,把官網的例子複製到自己項目中,然後修改成自己的代碼,慢慢來就懂了。。。。

首先解釋一下官網例1:自定義容器中各參數和方法的作用

MyBody():這個方法是自定義滾動的範圍是整個body滾動還是在你自定義的層裏面滾動(個人認爲可以用css的相對定位,絕對定位,overflow來實現同樣的效果,所以這個方法看喜好來。);

變量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來轉化下數據,感嘆號強調。

 

 


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章