React Ant Design Mobile 中 ListView 簡單使用,搞懂每一行代碼


初用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 Native https://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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM