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

前端之家收集整理的这篇文章主要介绍了React+dva+webpack+antd-mobile 实战分享(二)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

第一篇 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事件传递给子组件,另一界面 <TabButton ButtonClick ={this.ButtonClick.bind(this)} />就可以取到此组件传递过去的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(
          <TabPane tab={`${channels[i].title}`} key={`${parseInt(channels[i].ID)}`}>
            <div style={{ display: 'flex',alignItems: 'center',justifyContent: 'center',border:'none' }}>
            </div>
          </TabPane>
        )
      }
    }
    return result
  }

  _getMore() {
    this.props.dispatch(
      routerRedux.push('/moreChannel')
    )
  }

  render() {
    return(
      <div style={{position:'fixed',top:44,zIndex:999,backgroundColor:'#fff',width:(width/7)*6}}>
        <Tabs defaultActiveKey="1"
              pageSize={7}
              onTabClick={(key) => {this._handleTabClick(key)}}
              swipeable = {false}
          >
          {this._renderList()}
        </Tabs>
        <p style={styles.moreChannel} onClick={() => this._getMore()}>
          <img style={{width:26,height:26,marginTop:8,marginLeft:14}} src={require('../../assets/list/addchannel@2x.png')} alt=""/>
        </p>
      </div>
    )
  }
}

const styles = {
  moreChannel:{
    position:'absolute',top:0,right:-width/7,zIndex:9999,width:width/7,height:42,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,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(
      <div style={defaultStyle}>
        {content}
      </div>
    )
  }
}


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(
        <div style={defaultStyle}>
          <img src={require('../../assets/state/fail@2x.png')} alt="" style={{width:32,height:40}} />
          <span>正在加載喔~</span>
        </div>
      )
    } else if(hasMore === false){
      content = "没有更多"
    }

    return(
      <div style={defaultStyle}>
        {content}
      </div>
    )
  }
}


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',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,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,});
        }).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(
          <p style={styles.more}>更新了{this.state.newsLength}条内容</p>
        )
      }else{
        return(
          <p style={styles.more}>暂無更新推送</p>
        )
      }
    }else{
      return(
        <p></p>
      )
    }
  }

  render(){
    const {data,hasMore} = this.state
    return (
      <div>
        <TabButton
          ButtonClick = {this.ButtonClick.bind(this)}
          />
        <p style={{width:100,height:80}}></p>
        <ReactPullLoad
          downEnough={50}
          action={this.state.action}
          handleAction={this.handleAction}
          hasMore={hasMore}
          distanceBottom={10}
          HeadNode={HeadNode}
          FooterNode={FooterNode}
          >
          <ul className="test-ul">
            {
              data.map( (str,index )=>{
                if(str.images[0] != ''){
                  return <li key={index}>
                    <div style={styles.news} onClick = {() => this._routerDetail(index)}>
                      <img src={str.images[0]} style={styles.imgStyle} />
                      <p style={styles.newsTitle}>{str.title}</p>
                      <p style={{fontSize:12,color:'#ccc',borderWidth:1}}><span style={{color:'#03D7FF'}}>{str.source}</span> | {str.publishTime}</p>
                    </div>
                  </li>
                }else{
                  return <li key={index}>
                    <div style={styles.news} onClick = {() => this._routerDetail(index)}>
                      <p style={styles.newsTitle}>{str.title}</p>
                      <p style={{fontSize:12,borderWidth:1}}><span style={{color:'#03D7FF'}}>{str.source}</span> | {str.publishTime}</p>
                    </div>
                  </li>
                }
              })
            }
          </ul>
        </ReactPullLoad>
        <div>
        </div>
        {this._renderShow()}
      </div>
    )
  }

}


const styles = {
  more: {
    width:width,backgroundColor:'#FFDB01',position:'absolute',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,position: 'absolute',right:0,zIndex:9999
  }
}
function indexList({ indexList }) {
  return { indexList };
}
export default connect(indexList)(indexTab);

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

猜你在找的React相关文章