這個插件給我最大的體會是,官網看不懂的,把官網的例子複製到自己項目中,然後修改成自己的代碼,慢慢來就懂了。。。。
首先解釋一下官網例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來轉化下數據,感嘆號強調。