zoukankan      html  css  js  c++  java
  • 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/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={{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/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 ={
       "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={{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',
          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(
              <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={{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,color:'#ccc',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,
        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-30,
        //height:100
      },
      newsTitle: {
        fontSize:18,
        marginTop:10,
        marginBottom:10
      },
      moreTab: {
        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);
    

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

  • 相关阅读:
    hibernate执行createSQLQuery时字段重名的问题
    注意JDBC驱动的版本和JDK的版本是否匹配 JDBC连接Mariadb
    MariaDBConn用于链接MariaDB的管理类
    PLSQL Developer对oracle中的数据进行备份恢复
    JQuery判断浏览器类型
    IE与非IE window.onload调用
    如何升级centos到最新版本
    bootstrap 后台模板
    FontAwesome 4.7.0 中完整的675个图标样式CSS参考
    Linux Crontab及使用salt进行管理
  • 原文地址:https://www.cnblogs.com/10manongit/p/12879720.html
Copyright © 2011-2022 走看看