React+dva+webpack+antd-mobile 实战分享(二)

2021-03-08 00:29

阅读:714

第一篇 https://segmentfault.com/a/11...

在上一篇文章中教给大家了怎么搭建项目的架子;那么今天我们就来说一下项目里的导航和列表的实现

导航

技术图片

废话不说啦 下面直接给大家讲一下代码
项目用的antd-mobile的框架 应该没什么难度,我相信大家认真看文档的都能布局出来;

TabButton.js

import React, { Component } from ‘react‘;
import { Tabs, WhiteSpace,ListView,Toast} from ‘antd-mobile‘;
import { routerRedux } from ‘dva/router‘;
import { connect } from ‘dva‘;
import Request from ‘../common/fetch‘
import {width,height} from ‘../common/style‘;

const TabPane = Tabs.TabPane;

class TabButton extends Component {
  constructor(props) {
    super(props);
    this.state = {
      channels: []
    }
  }
 
  componentDidMount() {
  // 这个地方是封装的fetch请求;
    Request(‘/api/article/channel‘,{
      secret:1111,
    },((res) => {
      this.setState({
        channels: res.result.channels
      })
      // 请求过来的数据全部存下来,以便后期调用,同时可以减少请求
      this.props.dispatch({
        type: ‘indexList/TabData‘,
        payload: res.result.channels,
      });
    }))
  }
//这个点需要注意:此处是将click事件传递给子组件,另一界面 就可以取到此组件传递过去的click事件;
  _handleTabClick(key){
    this.props.ButtonClick(key);
  }

  _renderList() {
    let result = [];
    const channels = this.state.channels;
    for(let i in channels) {
      if(channels[i].attval == 1 || channels[i].attval == 2){
        result.push(
          
) } } return result } _getMore() { this.props.dispatch( routerRedux.push(‘/moreChannel‘) ) } render() { return(
{this._handleTabClick(key)}} swipeable = {false} > {this._renderList()}

this._getMore()}>

) } } const styles = { moreChannel:{ position:‘absolute‘, top:0, right:-width/7, zIndex:9999, width:width/7, height:42, backgroundColor:‘#fff‘, alignItems:‘center‘, justifyContent:‘center‘ } } function indexList({indexList}) { return { indexList }; } export default connect(indexList)(TabButton);

fetch.js

export default function Request(url,body,callback){
  fetch(url,{
    method: ‘POST‘,
    mode: "cors",
    headers: {
      ‘Content-Type‘: ‘application/json‘,
      ‘Accept‘: ‘application/json‘
    },
    body: JSON.stringify(body)
  }).then((res) => res.json()).then((res) => {
    callback(res)
  }).catch((err) => {
    console.log(err)
  })
}

列表

indexTab.js

import React, { Component,PureComponent,PropTypes } from ‘react‘;
import { Tabs, WhiteSpace,ListView,Toast} from ‘antd-mobile‘;
import { routerRedux } from ‘dva/router‘;
import { connect } from ‘dva‘;
import ReactPullLoad,{ STATS } from ‘react-pullload‘;
import TabButton from ‘./TabButton‘;
import {width,height} from ‘../common/style‘;

let devicenum = localStorage.getItem(‘devicenum‘)
const loadMoreLimitNum = 10;

const defaultStyle ={
  width: "100%",
  textAlign: "center",
  fontSize: "14px",
  lineHeight: "1.5",
  paddingTop:"12px",
  color:‘#ccc‘
}

class HeadNode extends PureComponent{

  static propTypes = {
    loaderState: PropTypes.string.isRequired,
  };

  static defaultProps = {
    loaderState: STATS.init,
  };

  render(){
    const {
      loaderState
      } = this.props

    let content = ""
    if(loaderState == STATS.pulling){
      content = "下拉刷新"
    } else if(loaderState == STATS.enough){
      content = "松开刷新"
    } else if(loaderState == STATS.refreshing){
      content = "正在刷新..."
    } else if(loaderState == STATS.refreshed){
      content = "刷新成功"
    }

    return(
      
{content}
) } } class FooterNode extends PureComponent{ static propTypes = { loaderState: PropTypes.string.isRequired, hasMore: PropTypes.bool.isRequired }; static defaultProps = { loaderState: STATS.init, hasMore: true }; render(){ const { loaderState, hasMore } = this.props let content = "" if(loaderState == STATS.loading){ return(
正在加載喔~
) } else if(hasMore === false){ content = "没有更多" } return(
{content}
) } } class indexTab extends Component { constructor(props) { super(props) this.state = { channels : [], channelid : 1, showT:false, loading : false, hasMore: true, data: [], action: STATS.init, index: loadMoreLimitNum, newsLength:‘‘ } } componentDidMount() { this.getListData(this.state.channelid); } getListData(channelid) { // List fetch(‘/api/article‘,{ method: ‘POST‘, mode: "cors", headers: { ‘Content-Type‘: ‘application/json‘, ‘Accept‘: ‘application/json‘ }, body: JSON.stringify({ channelID: channelid, type: 0, pageSize: 10, dt : 2, action: 1, devicenum:devicenum }) }).then((res) => res.json()).then((res) => { this.setState({ data: res.result.news, newsLength:res.result.news.length }) this.props.dispatch({ type: ‘indexList/detailData‘, payload: res.result.news, }); }).then(() => { setTimeout(() => { this.setState({ showT : true }) },1900) }).then(() => { setTimeout(() => { this.setState({ showT : false }) },2900) }).catch((err) => { console.log(err) }) } handleAction = (action) => { console.info(action, this.state.action,action === this.state.action); if(action === this.state.action){ return false } if(action === STATS.refreshing){//刷新 this.handRefreshing(); } else if(action === STATS.loading){ this.handLoadMore(); } else{ this.setState({ action: action }) } } handRefreshing = () =>{ if(STATS.refreshing === this.state.action){ return false } this.getListData(this.state.channelid) setTimeout(()=>{ this.setState({ action: STATS.refreshed, index: loadMoreLimitNum }); }, 3000) } handLoadMore = () => { if(STATS.loading === this.state.action){ return false } setTimeout(()=>{ if(this.state.index === 0){ this.setState({ action: STATS.reset, hasMore: false }); } else{ fetch(‘/api/article‘,{ method: ‘POST‘, headers: { ‘Content-Type‘: ‘application/json;charset=UTF-8‘, ‘Accept‘: ‘application/json‘ }, body: JSON.stringify({ channelID: this.state.channelid, type: 0, pageSize: 10, dt : 2, action: 1, devicenum:devicenum }) }).then((res) => res.json()).then((res) => { this.setState({ data: [...this.state.data,...res.result.news], action: STATS.reset, index: this.state.index - 1 }) this.props.dispatch({ type: ‘indexList/detailData‘, payload: [...this.state.data,...res.result.news], }); }).then(() => { console.log(this.state.showT) setTimeout(() => { this.setState({ showT : true }) },1900) }).then(() => { setTimeout(() => { this.setState({ showT : false }) },2900) }).catch((err) => { console.log(err) }) } }, 3000) this.setState({ action: STATS.loading }) } //跳转到详情页 _routerDetail(index) { localStorage.setItem(‘detailid‘,index) this.props.dispatch( routerRedux.push(`/detail/${index}`) ) } //Tab 切换重新调取 ButtonClick(key) { this.getListData(key); this.setState({ channelid:key }) } _renderShow() { if(this.state.showT == true){ if(this.state.newsLength != 0){ return(

更新了{this.state.newsLength}条内容

) }else{ return(

暂無更新推送

) } }else{ return(

) } } render(){ const {data,hasMore} = this.state return (

    { data.map( (str, index )=>{ if(str.images[0] != ‘‘){ return
  • this._routerDetail(index)}>

    {str.title}

    {str.source} | {str.publishTime}

  • }else{ return
  • this._routerDetail(index)}>

    {str.title}

    {str.source} | {str.publishTime}

  • } }) }
{this._renderShow()}
) } } const styles = { more: { width:width, backgroundColor:‘#FFDB01‘, position:‘absolute‘, zIndex:9999, top:86, textAlign:‘center‘, padding:5, fontSize:14, display:‘block‘, }, news: { padding:15, justifyContent:‘center‘, alignItems:‘center‘ }, imgStyle: { width:width-30, //height:100 }, newsTitle: { fontSize:18, marginTop:10, marginBottom:10 }, moreTab: { width:width-(width/7)*6, height:43, backgroundColor:‘#fff‘, position: ‘absolute‘, justifyContent:‘center‘, alignItems:‘center‘, top:44, right:0, zIndex:9999 } } function indexList({ indexList }) { return { indexList }; } export default connect(indexList)(indexTab);

好啦 上述就是整个首页的主要代码,知道如何创建项目的你们可以尝试啦~~~


评论


亲,登录后才可以留言!