React Ant Design Mobile 中 ListView 簡單使用,搞懂每一行程式碼
阿新 • • 發佈:2020-10-12
初用Ant Design Mobile 中 ListView ,看到官方示例,新手朋友估計第一反應都是一臉蒙逼,現在我們寫一個最簡單的示例,除了讓程式碼運作起來,也讓大家知道每一行程式碼的作用
"dependencies": {
"antd": "^3.26.11",
"antd-mobile": "^2.3.1",
"axios": "^0.19.2",
"qs": "^6.9.1",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-redux": "^6.0.0",
"react-router-dom": "^4.3.1",
"redux": "^4.0.5"
}
直接上程式碼示例,基本只要把請求方法換一下,就能直接用,對於關鍵程式碼都有註釋,個人覺得比官網示例更簡單易上手
import React, { Component } from 'react'
import { NavBar, Icon, ListView, PullToRefresh, Toast } from 'antd-mobile'
import Api from '@/api/index.js'
class myCourse extends Component {
constructor(props) {
super(props)
// 建立ListViewDataSource物件
const dataSource = new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2 // rowHasChanged(prevRowData, nextRowData); 用其進行資料變更的比較
})
this.state = {
dataSource,
datas: [],
pageNo: 1,
pageSize: 2,
hasMore: true,
refreshing: true,
isLoading: true,
dataArr: [],
}
}
componentDidMount() {
this.getData(true)
}
getData(ref = false) {
//獲取資料
var para = {}
para.pageSize = this.state.pageSize
para.pageNo = this.state.pageNo
Api.get('http://www.xxx.com/api/myCourse', para, res => {
const dataList = res.data.list
const len = dataList.length
if (len <= 0) { // 判斷是否已經沒有資料了
this.setState({
refreshing: false,
isLoading: false,
hasMore: false
})
Toast.info('沒有資料了~', 1)
return false
}
if (ref) {
//這裡表示重新整理使用
// 下拉重新整理的情況,重新新增資料即可(這裡等於只直接用了第一頁的資料)
this.setState({
pageNo: this.state.pageNo,
dataSource: this.state.dataSource.cloneWithRows(dataList), // 資料來源中的資料本身是不可修改的,要更新datasource中的資料,請(每次都重新)呼叫cloneWithRows方法
hasMore: true, // 下拉重新整理後,重新允許開下拉載入
refreshing: false, // 是否在重新整理資料
isLoading: false, // 是否在載入中
dataArr: dataList // 儲存資料進state,在下拉載入時需要使用已有資料
})
} else {
// 這裡表示上拉載入更多
// 合併state中已有的資料和新增的資料
var dataArr = this.state.dataArr.concat(dataList) //關鍵程式碼
this.setState({
pageNo: this.state.pageNo,
dataSource: this.state.dataSource.cloneWithRows(dataArr), // 資料來源中的資料本身是不可修改的,要更新datasource中的資料,請(每次都重新)呼叫cloneWithRows方法
refreshing: false,
isLoading: false,
dataArr: dataArr // 儲存新資料進state
})
}
})
}
// 下拉重新整理
onRefresh = () => {
this.setState({
refreshing: true,
isLoading: true,
pageNo: 1 // 重新整理嘛,一般載入第一頁,或者按你自己的邏輯(比如每次重新整理,換一個隨機頁碼)
}, ()=>{
this.getData(true)
})
}
// 滑動到底部時載入更多
onEndReached = (event) => {
// 載入中或沒有資料了都不再載入
if (this.state.isLoading || !this.state.hasMore) {
return
}
this.setState({
isLoading: true,
pageNo: this.state.pageNo + 1, // 載入下一頁
}, ()=> {
this.getData(false)
})
}
render() {
const row = (rowData, sectionID, rowID) => {
// 這裡rowData,就是上面方法cloneWithRows的陣列遍歷的單條資料了,直接用就行
return (
<div key={rowID} className="article">
<div className="article-title">
{rowData.courseTitle}
</div>
<div className="article-body">
<div className="hidden">id: {rowData.id}</div>
<div ><label className="label-3em">姓名</label>:{ rowData.userName }</div>
</div>
</div>
)
}
return (
<div className="content-bg">
<div className="content-box">
<ListView
ref={el => this.lv = el}
dataSource={this.state.dataSource}
renderHeader={() => (<NavBar
mode="light"
icon={<Icon type="left" />}
onLeftClick={() => this.props.history.push('/usercenter') }
>我的課程</NavBar>)}
renderFooter={() => (<div className="footer">{this.state.isLoading ? '載入中...' : '暫無更多資料'}</div>)}
renderRow={row}
useBodyScroll
pullToRefresh={<PullToRefresh
refreshing={this.state.refreshing}
onRefresh={this.onRefresh}
/>}
onEndReachedThreshold={10}
onEndReached={this.onEndReached}
pageSize={5}
/>
</div>
</div>
);
}
}
export default myCourse
如果不使用下拉重新整理,那程式碼就更少了,關鍵程式碼就是要合併新增資料和之前載入的資料,concat方法即可
var dataArr = this.state.dataArr.concat(dataList)
然後就是更新到dataSource中,需要用cloneWithRows方法,這點可以參考官方文件的解釋,這裡的官方文件不是antd文件,是React Nativehttps://reactnative.cn/docs/0.45/listviewdatasource.html關於ListView.DataSource的介紹,讀懂的這個,再用Antd ListView就好理解多了
import React, { Component } from 'react'
import { NavBar, Icon, ListView, PullToRefresh, Toast } from 'antd-mobile'
import Api from '@/api/index.js'
class myCourse extends Component {
constructor(props) {
super(props)
// 建立ListViewDataSource物件
const dataSource = new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2 // rowHasChanged(prevRowData, nextRowData); 用其進行資料變更的比較
})
this.state = {
dataSource,
datas: [],
pageNo: 1,
pageSize: 2,
hasMore: true,
refreshing: true,
isLoading: true,
dataArr: [],
}
}
componentDidMount() {
this.getData(true)
}
getData(ref = false) {
//獲取資料
var para = {}
para.pageSize = this.state.pageSize
para.pageNo = this.state.pageNo
Api.get('http://www.xxx.com/api/myCourse', para, res => {
const dataList = res.data.list
const len = dataList.length
if (len <= 0) { // 判斷是否已經沒有資料了
this.setState({
refreshing: false,
isLoading: false,
hasMore: false
})
Toast.info('沒有資料了~', 1)
return false
}
// 這裡表示上拉載入更多
// 合併state中已有的資料和新增的資料
var dataArr = this.state.dataArr.concat(dataList) //關鍵程式碼
this.setState({
pageNo: this.state.pageNo,
dataSource: this.state.dataSource.cloneWithRows(dataArr), // 資料來源中的資料本身是不可修改的,要更新datasource中的資料,請(每次都重新)呼叫cloneWithRows方法
refreshing: false,
isLoading: false,
dataArr: dataArr // 儲存新資料進state
})
})
}
// 滑動到底部時載入更多
onEndReached = (event) => {
// 載入中或沒有資料了都不再載入
if (this.state.isLoading || !this.state.hasMore) {
return
}
this.setState({
isLoading: true,
pageNo: this.state.pageNo + 1, // 載入下一頁
}, ()=> {
this.getData(false)
})
}
render() {
const row = (rowData, sectionID, rowID) => {
// 這裡rowData,就是上面方法cloneWithRows的陣列遍歷的單條資料了,直接用就行
return (
<div key={rowID} className="article">
<div className="article-title">
{rowData.courseTitle}
</div>
<div className="article-body">
<div className="hidden">id: {rowData.id}</div>
<div ><label className="label-3em">姓名</label>:{ rowData.userName }</div>
</div>
</div>
)
}
return (
<div className="content-bg">
<div className="content-box">
<ListView
ref={el => this.lv = el}
dataSource={this.state.dataSource}
renderHeader={() => (<NavBar
mode="light"
icon={<Icon type="left" />}
onLeftClick={() => this.props.history.push('/usercenter') }
>我的課程</NavBar>)}
renderFooter={() => (<div className="footer">{this.state.isLoading ? '載入中...' : '暫無更多資料'}</div>)}
renderRow={row}
useBodyScroll
onEndReachedThreshold={10}
onEndReached={this.onEndReached}
pageSize={5}
/>
</div>
</div>
);
}
}
export default myCourse