<repo_name>weiyufangchen/yanxuan-react<file_sep>/README.md
## react项目

### day01

```
1.  复习react相关知识，语法，和作用
2. 搭建脚手架项目
3. 配置stylus语法编译
4. 搭建路由和页面底部路由切换
5. 首页静态页面完成
bug：
	样式重叠
	多个文件的样式类名相同，导致样式被覆盖
解决方法：修改类名	
```

### day02

```
完成5个路由页面和手机登录，邮箱登录页面，并完成登录验证、定时器等功能
动态添加数据完成80%
bug：
	1. 数据为null或者undefined
		解决：绑定数据之前判断数据是否请求成功，是否保存在state中，再去获取遍历
	2. 轮播图bug
		解决：componentDidUpdate函数中将swiper实例对象挂载到this上，然后判断是否已经创建，已经创建则不需要再次创建
```

### day03

```
npm run build
打包发布生成build文件
```

<file_sep>/src/containers/profile/Profile.jsx
/*
个人中心/登录/注册组件
 */
import React, {Component} from 'react'
// react-router 提供了一个withRouter组件
// withRouter可以包装任何自定义组件，将react-router 的 history,location,match 三个对象传入
import {withRouter} from 'react-router-dom'

import ShiwuHeader from '../../components/shiwuHeader/ShiwuHeader'
import './profile.styl'

class Profile extends Component {
  render () {
    return (
      <div className='profile'>
        {/* 登录/注册，个人中心头部 */}
        <ShiwuHeader/>
        <div className="loginWrap" style={{height: '1246px',display: 'block'}}>
          <div className="login-type">
            {/* 登录按钮 */}
            <div className="container">
              <div className="logoWrapper">
                <img src="//yanxuan.nosdn.127.net/bd139d2c42205f749cd4ab78fa3d6c60.png" alt=""/>
              </div>
              <div className="btnWrapper">
                <div className="btn btn-xl btn-block phone-login"
                     onClick={() => this.props.history.replace('/phonelogin')}>
                  <i className="icon icon-loginPhone"></i>
                  <span>手机号码登录</span>
                </div>
                <div className="btn btn-xl btn-block email-login"
                  onClick={() => this.props.history.replace('/emaillogin')}>
                  <i className="icon icon-loginEmail"></i>
                  <span>邮箱账号登录</span>
                </div>
                <div className="register" onClick={() => this.props.history.replace('/profile')}>
                  <span>手机号快捷注册 > </span>
                </div>
              </div>
            </div>
            {/* 联系方式 */}
            <ul className="contact">
              <li className="itemWrap">
            <span className="item">
              <i className="iconfont icon-weixin1"></i>
              <span className="name">微信</span>
            </span>
              </li>
              <li className="itemWrap">
            <span className="item">
              <i className="iconfont icon-qq"></i>
              <span className="name">QQ</span>
            </span>
              </li>
              <li className="itemWrap">
            <span className="item">
              <i className="iconfont icon-sinaweibo"></i>
              <span className="name">微博</span>
            </span>
              </li>
            </ul>
          </div>
        </div>
      </div>
    )
  }
}

export default withRouter(Profile)
<file_sep>/src/api/index.js
/*
包含多个接口的请求函数的模块
函数的返回值：promise对象
 */
import ajax from './ajax'
// 获取首页数据
export const reqHomeData = () => ajax('/homedata')
export const reqNavData = () => ajax('/navdata')
export const reqTopicData = () => ajax('/topicdata')
<file_sep>/src/components/homeHeader/HomeHeader.jsx
/*
首页头部组件HomerHeader
 */
import React, {Component} from 'react'
//引入滚动的插件库
import BScroll from 'better-scroll'
// 引入样式
import './homeHeader.styl'

export default class HomeHeader extends Component {
  state = {
    navList: ['推荐', '居家', '鞋包配饰', '服装', '电器', '洗护', '饮食', '餐厨', '婴童', '文体', '特色区'],
    currentIndex: 0
  }

  componentDidMount() {
    new BScroll('.header-nav', {
      scrollX: true,
      click: true
    })
  }

  addClass = (index) => {
  //  更新state
    this.setState({
      currentIndex: index
    })
  }

  render() {
    const {navList, currentIndex} = this.state
    return (
      <div>
        <div className="home-header">
          {/*首页搜索*/}
          <div className="header-search">
            <a href="javascript:;" className="logo"></a>
            <div className="search">
              <i className="iconfont"></i>
              <span>搜索商品, 共11765款好物</span>
            </div>
          </div>
          {/*首页导航*/}
          <div ref='headerNav' className="header-nav border-1px">
            <ul className="nav-list">
              {
                navList.map((item, index) => {
                  return (
                    <li className="list-item" key={index} onClick={() => this.addClass(index)}>
                      <span ref="span" className={index === currentIndex ? 'active' : ''}>{item}</span>
                    </li>
                  )
                })
              }
            </ul>
          </div>
        </div>
      </div>
    )
  }
}
<file_sep>/src/redux/action-types.js
/*
包含多个action type常量名称的模块
 */
export const RECEIVE_HOMEDATA = 'receive_homedata' // 接收首页数据
export const RECEIVE_NAVDATA = 'receive_navdata'
export const RECEIVE_TOPICDATA = 'receive_topicdata'

// 请求失败

export const ERR_MSG = 'ERR_MSG'
<file_sep>/src/redux/store.js
/*
redux管理状态的核心对象
 */
import {createStore, applyMiddleware} from 'redux'
// 应用异步中间件
import thunk from 'redux-thunk'
// 使用插件工具查看state
import {composeWithDevTools} from 'redux-devtools-extension'

import reducers from './reducers'  // 它是一个个的reducer函数

export default createStore(reducers, composeWithDevTools(applyMiddleware(thunk)))
<file_sep>/src/containers/shiwu/shiwuBanner/ShiwuBanner.jsx
/*
识物轮播图
 */
import React, {Component} from 'react'
import Swiper from 'swiper'

import './shiwuBanner.styl'

export default class ShiwuBanner extends Component {

  componentDidUpdate () {
    new Swiper('.swiper-container-banner1', {
      loop: true,
      zoom: true,
    })
  }

  render () {
    const banner = this.props.data
    return (
      <div className="banner-wrapper">
        <div className="carousel banner">
          <div className="swiper-container-banner1">
            <div className="swiper-wrapper">
              {
                banner ? (
                  banner.map((item, index) => {
                    return (
                      <div className="swiper-slide" style={{width: '690px'}} key={index}>
                        <a href="javascript:;">
                          <img src={item.picUrl} alt=""/>
                          <div className="content">
                            <div className="subTitle">{item.subTitle}</div>
                            <div className="title">{item.title}</div>
                            <div className="desc">{item.desc}</div>
                          </div>
                        </a>
                      </div>
                    )
                  })
                ) : null
              }
            </div>
          {/* Add Pagination */}
          <div className="swiper-pagination"></div>
        </div>
      </div>
  </div>
    )
  }
}
<file_sep>/src/components/modelHeader/ModelHeader.jsx
/*
通用的模版头部
 */
import React, {Component} from 'react'
import './modelHeader.styl'

export default class ModelHeader extends Component {
  render () {
    return (
      <header className="hd-one">
        <a className="more" href="javascript:;">
          <span>品牌制造商直供</span>
          <i className="icon icon-go"></i>
        </a>
      </header>
    )
  }
}<file_sep>/src/api/ajax.js
/*
ajax请求函数模块
函数的返回值为promise对象
 */
import axios from 'axios'

export default function ajax(url='', data={}, type='GET') {
  // 返回一个自己创建的promise对象，为了能得到的不是response，而是得到response.data的数据
  return new Promise(function (resolve, reject) {
    let promise
    // 如果发送的GET请求
    if (type === 'GET') {
      //  将data中所有数据作为请求参数传到url中
      //  准备url query 参数数据
      let queryStr = '';
      Object.keys(data).forEach(key => {  // keys() 得到对象自身的所有属性名组成的数组
        const value = data[key]  // 拿到对应的属性值
        //  拼串
        queryStr += key + '=' + value + '&'  // 最后会多一个&
      });
      if (queryStr) {  // 如果确实发送了请求数据
        //  去除最后的&
        queryStr = queryStr.substring(0, queryStr.length - 1)
        //  加上问号
        queryStr = '?' + queryStr
      }
      //  拿到response.data
      promise = axios.get(url + queryStr);
    } else {  // POST请求
      promise = axios.post(url, data)
    }
    promise.then(response => {
      // 请求成功
      resolve(response.data)
    }).catch(err => {  // 请求失败
      reject(err)
    })
  })
}
<file_sep>/src/components/limitTimeBuy/LimitTimeBuy.jsx
/*
限时购组件：UI组件
 */
import React, {Component} from 'react'

import './limitTimeBuy.styl'

export default class LimitTimeBuy extends Component {

  state = {
    hour: '00', // 初始化限时购
    min: '10',
    second: '20',
    startTime: 20
  }

  componentDidMount () {
    this.countDown()
  }

  // 倒计时，限时购
  countDown = () => {
  //  获取当前时间
    let date = new Date()
    let start = date.getTime()
  //  设置截止时间
    let endDate = new Date("2018-8-18 20:00:00")
    let end = endDate.getTime()
  //  时间差
    let deltaTime = end - start
  // 定义变量 d,h,m,s保存倒计时的时间
    let d, h, m, s
    if (deltaTime >= 0) {
      d = Math.floor(deltaTime / 1000 / 60 / 60 / 24)
      h = Math.floor(deltaTime / 1000 / 60 / 60 % 24)
      m = Math.floor(deltaTime / 1000 / 60 % 60)
      s = Math.floor(deltaTime / 1000 % 60)
    }
  //  更新状态
    if (h < 10) {
      this.setState({
        hour: `0${h}`
      });
    } else {
      this.setState({
        hour: `${h}`
      })
    }
    if (m < 10) {
      this.setState({
        min: `0${m}`
      });
    } else {
      this.setState({
        min: `${m}`
      });
    }
    if (s < 10) {
      this.setState({
        sec: `0${s}`
      });
    } else {
      this.setState({
        second: `${s}`
      });
    }
  //  递归调用
    setTimeout(this.countDown, 1000)
  }

  render () {
    const flashSaleIndexVO = this.props.data
    const {hour, min, second, startTime} = this.state
    return (
      flashSaleIndexVO ? (
        <div>
          <a href="javascript:;">
            <div className="indexFlash">
              <div className="left-item">
                <div className="title">严选限时购</div>
                <div className="countdown">
                  <span className="hours">{hour}</span>
                  <span className="colon">:</span>
                  <span className="mins">{min}</span>
                  <span className="colon">:</span>
                  <span className="secs">{second}</span>
                </div>
                <div className="next-title">
            <span>
              <span>下一场</span>
              <span>{startTime}:00</span>
              <span>开始</span>
            </span>
                </div>
              </div>
              <div className="right-item">
                <img src={flashSaleIndexVO.primaryPicUrl}/>
                <div className="price">
                  <div className="price-now">
                    <span>￥{flashSaleIndexVO.activityPrice}</span>
                  </div>
                  <div className="price-origin">
                    {/* 添加伪类做删除线 */}
                    <span className="t">￥{flashSaleIndexVO.originPrice}</span>
                  </div>
                </div>
              </div>
            </div>
          </a>
        </div>
      ) : null
    )
  }
}


<file_sep>/src/containers/cart/Cart.jsx
/*
购物车路由组件
 */
import React, {Component} from 'react'
import {NavLink} from 'react-router-dom'

import './cart.styl'
import FooterGuide from '../../components/footerGuide/FooterGuide'

export default class Cart extends Component {
  render () {
    return (
      <div>
        <div className='cart'>
          {/* cart头部 */}
          <div className="cartHeader" style={{height: '88px'}}>
            <div className="hd">
              <div className="headWrapper">
                <span className="logo">购物车</span>
                <div className="right">
                  <NavLink className="cartCoupon" to='/profile'>领券</NavLink>
                </div>
              </div>
            </div>
          </div>
          {/* 服务：30天无忧退货 */}
          <div className="service">
            <ul className="serviceList">
              <li className="item">
                <i className="icon icon-servicePolicy"></i>
                <span>30天无忧退货</span>
              </li>
              <li className="item">
                <i className="icon icon-servicePolicy"></i>
                <span>48小时快速退款</span>
              </li>
              <li className="item">
                <i className="icon icon-servicePolicy"></i>
                <span>满88元免邮费</span>
              </li>
            </ul>
          </div>
          {/* 购物车空状态的默认页面 */}
          <div className="defaultPage noCart-defaultPage">
            <div className="container">
              <div className="noCart-img"></div>
              <div className="txt noCart-login">
                <div className="noCart-title">去添加点什么吧</div>
                <div className="noCart-btn">登录</div>
              </div>
            </div>
          </div>
        </div>
        <FooterGuide/>
      </div>
    )
  }
}
<file_sep>/src/components/footerGuide/FooterGuide.jsx
/*
底部导航的组件FooterGuide
 */
import React, {Component} from 'react'
import {
  withRouter,
  NavLink,
} from 'react-router-dom'

import './footerGuide.styl'

class FooterGuide extends Component {

  render() {
    return (
      <footer className="footer_guide border-1px">
        <NavLink href="javascript:;" className="guide_item" activeClassName='active' to='/home'>
          <i className="iconfont icon-shouye"></i>
          <span>首页</span>
        </NavLink>
        <NavLink href="javascript:;" className="guide_item" activeClassName='active' to='/shiwu'>
          <i className="iconfont icon-fangkuaidagou-weixuanzhong"></i>
          <span>识物</span>
        </NavLink>
        <NavLink href="javascript:;" className="guide_item" activeClassName='active' to='/category'>
          <i className="iconfont icon-chouti"></i>
          <span>分类</span>
        </NavLink>
        <NavLink href="javascript:;" className="guide_item" activeClassName='active' to='/cart'>
          <i className="iconfont icon-gouwuche"></i>
          <span>购物车</span>
        </NavLink>
        <NavLink href="javascript:;" className="guide_item" activeClassName='active' to='/profile'>
          <i className="iconfont icon-renwu"></i>
          <span>个人</span>
        </NavLink>
      </footer>
    )
  }
}

export default withRouter(FooterGuide)  // 向一般组件传递路由相关属性（history/location/match）
<file_sep>/src/index.js
/*
入口js
 */
import React from 'react'
import ReactDOM from 'react-dom'
import {Provider} from 'react-redux'
import {Route, Switch, HashRouter, Redirect} from 'react-router-dom'

import Home from './containers/home/Home'
import Shiwu from './containers/shiwu/Shiwu'
import Category from './containers/category/Category'
import Cart from './containers/cart/Cart'
import Profile from './containers/profile/Profile'
import PhoneLogin from './containers/phoneLogin/PhoneLogin'
import EmailLogin from './containers/emailLogin/EmailLogin'

import store from './redux/store'
// 引入mock文件
import './mock/mockServer'
// 引入混合stylus样式
import './assets/css/stylus/mixins.styl'
import 'swiper/dist/css/swiper.css'
import './assets/css/reset.css'
import './assets/css/index.css'
import './assets/js/index'
import 'antd-mobile/dist/antd-mobile.css';

ReactDOM.render((
  <Provider store={store}>
    <HashRouter>
      <Switch>
        <Route path='/phonelogin' component={PhoneLogin}/>
        <Route path='/emaillogin' component={EmailLogin}/>
        <Route path='/home' component={Home}/>
        <Route path='/shiwu' component={Shiwu}/>
        <Route path='/category' component={Category}/>
        <Route path='/cart' component={Cart}/>
        <Route path='/profile' component={Profile}/>
        <Redirect to='/home'/> {/* 默认路由 */}
      </Switch>
    </HashRouter>
  </Provider>
), document.getElementById('root'));
<file_sep>/src/containers/category/Category.jsx
/*
商品分类路由组件
 */
import React, {Component} from 'react'
import {connect} from 'react-redux'
import {getNavData} from '../../redux/actions'
import BScroll from 'better-scroll'

import './category.styl'

import CategoryHeader from '../../components/categoryHeader/CategoryHeader'
import FooterGuide from '../../components/footerGuide/FooterGuide'

class Category extends Component {
  // 定义初始index值，保存左侧导航li的下标
  state = {
    currentIndex: 0
  }

  componentDidMount() {
    // 调用action中函数，通知state更新
    this.props.getNavData()
  }

  componentDidUpdate() {
    new BScroll(this.refs.leftScroll, {click: true})
    // new BScroll(this.refs.rightScroll, {click: true})
  }

  // 监听li下标的改变
  activeChange = (index) => {
    //  更新state
    this.setState({
      currentIndex: index
    })
  }

  render() {
    const {navData} = this.props
    const {currentIndex} = this.state
    if (navData.length === 0) {
      return (<div></div>)
    }
    return (
      <div style={{backgroundColor: '#fff', width: '100%', height: '1734px'}}>
        {/* 商品分类头部搜索 */}
        <CategoryHeader/>
        {/* 商品左侧菜单导航 */}
        <div className="cateNavLeft" style={{left: 0}}>
          <div ref='leftScroll' style={{position: 'relative', height: '100%', width: '100%', overflow: 'hidden'}}>
            <ul className="cateNav">
              {
                navData.map((item, index) => {
                  return (
                    <li className={index === currentIndex ? 'item active' : 'item'} key={index}
                        onClick={() => this.activeChange(index)}>
                      <a className="txt" href="javascript:;">{item.name}</a>
                    </li>
                  )
                })
              }
            </ul>
          </div>
        </div>
        {/* 商品右侧展示列表 */}
        <div className="categoryNavRight">
          {
            navData.map((item, index) => {
              return (
                <div className={index === currentIndex ? 'wrap show': 'wrap hide'} key={index}>
                  <div className="banner" style={{backgroundImage: 'url(' + item.bannerUrl + ')'}}></div>
                  <div className="cateList">
                    <div className="hd">
                      <span className="text">
                        <span>{item.name}分类</span>
                      </span>
                    </div>
                    <div>
                      <ul className="list">
                        {
                          item.subCateList.map((subItem, index) => {
                            return (
                              <li className="cateItem" key={index}>
                                <a href="javascript:;">
                                  <div className="cateImgWraper">
                                    <img className="cateImg"
                                         src={subItem.wapBannerUrl}
                                         alt=""/>
                                  </div>
                                  <div className="name">{subItem.name}</div>
                                </a>
                              </li>
                            )
                          })
                        }
                      </ul>
                    </div>
                  </div>
                </div>
              )
            })
          }
        </div>
        <FooterGuide/>
      </div>
    )
  }
}

export default connect(
  state => ({navData: state.navData}),
  {getNavData}
)(Category)
<file_sep>/src/containers/emailLogin/EmailLogin.jsx
/*
邮箱登录组件
 */
import React, {Component} from 'react'
import {withRouter} from 'react-router-dom'
import {Modal} from 'antd-mobile'

import ShiwuHeader from '../../components/shiwuHeader/ShiwuHeader'
import codeImg from './captcha.svg'
import './emailLogin.styl'

const alert = Modal.alert

class EmailLogin extends Component {

  state = {
    email: '',
    pwd: '',
    captcha: '',
    showPwd: false  // 默认不显示
  }

  handleEmail = (event) => {
    this.setState({
      email: event.target.value
    })
  }
  handleCaptcha = (event) => {
    this.setState({
      captcha: event.target.value
    })
  }
  handlePwd = (event) => {
    this.setState({
      pwd: event.target.value
    })
  }
  changeShowPwd = () => {
    this.setState({
      showPwd: !this.state.showPwd
    })
  }

  goLogin = () => {
    const {email, pwd, captcha} = this.state;
    if (!email || !pwd) {
      alert('邮箱或密码错误', '请输入正确的邮箱', [
        {
          text: '取消', onPress: () => {
            this.setState({
              email: '',
              pwd: '',
              captcha: '',
            })
          }
        },
        {
          text: '确定', onPress: () => {
            this.setState({
              email: '',
              pwd: '',
              captcha: '',
            })
          }
        },
      ]);
      return
    } else if (captcha.toLowerCase() !== 'wk3v') {
      alert('验证码错误提示', '验证码不正确', [
        {
          text: '取消', onPress: () => {
            this.setState({
              captcha: '',
            })
          }
        },
        {
          text: '确定', onPress: () => {
            this.setState({
              captcha: '',
            })
          }
        },
      ]);
      return
    } else {
      this.props.history.replace('/home');
    }
  }

  render() {
    const {email, pwd, showPwd, captcha} = this.state
    return (
      <div className='emailLogin'>
        <ShiwuHeader/>
        <div className="loginWrap loginWrap-1">
          <div className="view">
            <div className="logo">
              <img src="http://yanxuan.nosdn.127.net/bd139d2c42205f749cd4ab78fa3d6c60.png" alt="logo"/>
            </div>
            <div className="userBox">
              <section className="login_message">
                <input type="text" value={email} onChange={this.handleEmail} placeholder='请输入邮箱账号'/>
              </section>
              <section className="login_verification">
                {
                  showPwd ? (
                    <input type="text" value={pwd} onChange={this.handlePwd} placeholder='请输入密码'/>
                  ) : (
                    <input type="password" value={pwd} onChange={this.handlePwd} placeholder='请输入密码'/>
                  )
                }
                <div className={showPwd ? 'switch_button on' : 'switch_button off'} onClick={this.changeShowPwd}>
                  <div className={showPwd ? 'switch_circle right' : 'switch_circle'}></div>
                  <span className="switch_text">{showPwd ? 'abc' : '...'}</span>
                </div>
              </section>
              <section className="login_message">
                <input type="text" placeholder="验证码" value={captcha} onChange={this.handleCaptcha}/>
                <img className="get_verification" src={codeImg} alt="captcha"
                     style={{width: 150, right: 20}}/>
              </section>
              <section className="login_hint">
                <span>注册账号</span>
                <span>忘记密码</span>
              </section>
            </div>
            <div className="btnWrapper">
              <div className="btn btn-xl btn-block phone-login" onClick={this.goLogin}>
                <span>登录</span>
              </div>
              <div className="btn btn-xl btn-block email-login"
                   onClick={() => this.props.history.replace('/profile')}>
                <span>其他登录方式</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    )
  }
}

export default withRouter(EmailLogin)
<file_sep>/src/containers/phoneLogin/PhoneLogin.jsx
/*
手机登录组件
 */
import React, {Component} from 'react'
import {withRouter} from 'react-router-dom'
import {Modal} from 'antd-mobile'

import ShiwuHeader from '../../components/shiwuHeader/ShiwuHeader'
import './phoneLogin.styl'

const {alert} = Modal

class PhoneLogin extends Component {

  state = {
    phone: '', // 手机号
    code: ''   // 验证码
  }

  // 手机号输出框值发生改变
  phoneNumber = (event) => {
    this.setState({
      phone: event.target.value
    })
  }
  // 手机验证码
  phoneCode = (event) => {
    this.setState({
      code: event.target.value
    })
  }

  // 验证手机号是否符合规范
  isRightPhone = () => {
    return /^1[34578]\d{9}$/.test(this.state.phone)
  }

  // 登录
  goLogin = () => {
    //  正则验证
    const reg = /^1[34578]\d{9}$/
    if (!reg.test(this.state.phone)) {  // 手机号不符合规范
      alert('提示', '手机号格式不正确', [
        {
          text: '取消', onPress: () => {
            this.setState({
              phone: '',
              code: ''
            })
          }
        },
        {
          text: '确定', onPress: () => {
            this.setState({
              phone: '',
              code: ''
            })
          }
        }
      ])
      return
    } else if (!/^\d{6}$/.test(this.state.code)) {
      alert('提示', '请输入6位数字验证码', [
        {
          text: '取消', onPress: () => {
            this.setState({
              code: ''
            })
          }
        },
        {
          text: '确定', onPress: () => {
            this.setState({
              code: ''
            })
          }
        }
      ]);
      return;
    } else {
      this.props.history.replace('/home')
    }
  }

  render() {
    const {phone, code} = this.state
    return (
      <div className='phoneLogin'>
        <ShiwuHeader/>
        <div className="loginWrap loginWrap-1">
          <div className="view">
            <div className="logo">
              <img src="http://yanxuan.nosdn.127.net/bd139d2c42205f749cd4ab78fa3d6c60.png" alt="logo"/>
            </div>
            <div className="userBox userBox-1">
              <section className="login_message">
                <input type="text" value={phone} onChange={this.phoneNumber} placeholder='请输入手机号'/>
              </section>
              <section className="login_verification">
                <input type="text" value={code} onChange={this.phoneCode} placeholder='请输入验证码'/>
                <div className="getWrap">
                  <a className="getsmscode" ref='getCode' onClick={this.getCode}>获取验证码</a>
                </div>
              </section>
              <section className="login_hint">
                <span>遇到问题？</span>
                <span>使用密码验证登录</span>
              </section>
            </div>
            <div className="btnWrapper">
              <div className="btn btn-xl btn-block phone-login" onClick={this.goLogin}>
                <span>登录</span>
              </div>
              <div className="btn btn-xl btn-block email-login"
                   onClick={() => this.props.history.replace('/profile')}>
                <span>其他登录方式</span>
              </div>
              <div className="register" onClick={() => this.props.history.replace('/profile')}>
                <span>注册账号 ></span>
              </div>
            </div>
          </div>
        </div>
      </div>
    )
  }
}

export default withRouter(PhoneLogin)
<file_sep>/src/containers/home/supply/Supply.jsx
/*
品牌制造商直供supply
 */
import React, {Component} from 'react'
import LazyLoad from 'react-lazyload'

import ModelHeader from '../../../components/modelHeader/ModelHeader'
import './supply.styl'

export default class Supply extends Component {
  render() {
    const tagList = this.props.data
    return (
      <div>
        <ModelHeader/>
        <div className="supplying">
          <ul className="list">
            {
              tagList ? (tagList.map(item => {
                return (
                  <li className="item" key={item.id}>
                    <a href="javascript:;">
                      <div className="cnt">
                        <h4 className="title">{item.name}</h4>
                        <div>
                          <span className="price1">{item.floorPrice}</span>
                          <span className="price2">元起</span>
                        </div>
                        {item.newOnshelf ? (<i className="icon icon-new"></i>) : null}
                      </div>
                      <LazyLoad>
                        <img src={item.picUrl} alt=''/>
                      </LazyLoad>
                    </a>
                  </li>
                )
              })) : null
            }
          </ul>
        </div>
      </div>
    )
  }
}
<file_sep>/src/containers/home/Home.jsx
/*
首页路由组件
 */
import React, {Component} from 'react'
import Swiper from 'swiper'
import {connect} from 'react-redux'
import LazyLoad from 'react-lazyload'
import ReactCssTransitionGroup from 'react-addons-css-transition-group'

import {getHomeData, getTopicData, getNavData} from '../../redux/actions'
// 引入样式
import './home.styl'
// 引入自定义模块组件
import HomeHeader from '../../components/homeHeader/HomeHeader'
import Carousel from './carousel/Carousel'
import Supply from './supply/Supply'
import Split from '../../components/split/Split'
import LimitTimeBuy from '../../components/limitTimeBuy/LimitTimeBuy'
import Weal from '../../components/weal/Weal'
import FooterGuide from '../../components/footerGuide/FooterGuide'
import GoTop from '../../components/goTop/GoTop'

class Home extends Component {

  state = {
    isShow: false,  // 默认不显示
    scrollTop: 0  // 滚动位移
  }

  componentDidMount() {
    this.props.getHomeData()
    window.addEventListener('scroll', this.handleScroll);
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.handleScroll);
  }

  handleScroll = (e) => {
    // console.log('浏览器滚动事件', window.pageYOffset)
    if (window.pageYOffset >= 800) {
      this.setState({
        isShow: true,
        scrollTop: window.pageYOffset
      });
    } else {
      this.setState({
        isShow: false,
        scrollTop: window.pageYOffset
      })
    }
  }

  componentDidUpdate() {
    new Swiper('.homeCarousel', {
      slidesPerView: 'auto',
      centeredSlides: false,
      zoom: true
    })
    new Swiper('.homeCarousel-topic', {
      slidesPerView: 'auto',
      centeredSlides: false,
      spaceBetween: 30
    })
  }


  render() {
    const {isShow, scrollTop} = this.state
    const {homeData} = this.props
    const {focusList, tagList, newItemNewUserList, popularItemList, flashSaleIndexVO, topicList, cateList} = homeData;
    return (
      <div className='home' ref='home'>
        {/* 头部：搜索导航 */}
        <HomeHeader/>
        {/* 首页轮播图 */}
        <Carousel data={focusList}/>
        <Split/>
        {/* 品牌制造商直供 */}
        <div className='template'>
          <Supply data={tagList}/>
        </div>
        <Split/>
        {/* 新品首发 */}
        <div className='template'>
          <div className='newItems'>
            <header className="hd">
              <a className="more" href="javascript:;">
                <span>新品首发</span>
                <div className="all">
              <span className="wrap">
                <span>查看全部</span>
                <i className="arrow-right"></i>
              </span>
                </div>
              </a>
            </header>
            <div className="goodGrid goodGrid-goodsList">
              <div className="inner swiper-container homeCarousel">
                <div className="list swiper-wrapper">
                  {
                    newItemNewUserList ? (
                      newItemNewUserList.map(item => {
                        return (
                          <div className="item swiper-slide" key={item.id}>
                            <a className="good" href="javascript:;">
                              <div className="hd">
                                <div className="wraper">
                                  <img src={item.listPicUrl}/>
                                </div>
                                <div className="desc">{item.simpleDesc}</div>
                              </div>
                              <div className="tagWrapper">
                                <p className="status anniversary">七夕推荐</p>
                              </div>
                              <div className="name">
                                <span>{item.name}</span>
                              </div>
                              <div className="newItemDesc">{item.simpleDesc}</div>
                              <div className="price">
                                <div>
                                  <span>￥{item.retailPrice}</span>
                                </div>
                              </div>
                              <span></span>
                              <div className="specification">
                                <div>3</div>
                                <div>色</div>
                                <div>可</div>
                                <div>选</div>
                              </div>
                            </a>
                          </div>
                        )
                      })
                    ) : null
                  }
                  <div className="item swiper-slide more">
                    <a href="javascript:;" style={{display: 'block', width: '100%', height: '100%',}}>
                      <span className="text">查看全部</span>
                    </a>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <Split/>
        {/* 人气推荐 */}
        <div className="template">  {/*加一个类template，给组件添加背景色白色*/}
          <div className='popularItemList'>
            <header className="hd">
              <a className="more" href="javascript:;">
                <span>人气推荐 · 好物精选</span>
                <div className="all">
              <span className="wrap">
                <span>查看全部</span>
                <i className="arrow-right"></i>
              </span>
                </div>
              </a>
            </header>
            <div className="goodGrid goodGrid-goodsList">
              <div className="inner swiper-container homeCarousel">
                <div className="list swiper-wrapper">
                  {
                    popularItemList ? (
                      popularItemList.map(item => {
                        return (
                          <div className="item swiper-slide" key={item.id}>
                            <a className="good" href="javascript:;">
                              <div className="hd">
                                <div className="wraper">
                                  <img
                                    src={item.listPicUrl}/>
                                </div>
                                <div className="desc">{item.simpleDesc}</div>
                              </div>
                              <div className="tagWrapper">
                                <p className="status anniversary">七夕推荐</p>
                              </div>
                              <div className="name">
                                <span>{item.name}</span>
                              </div>
                              <div className="newItemDesc">{item.simpleDesc}</div>
                              <div className="price">
                                <div>
                                  <span>￥{item.retailPrice}</span>
                                </div>
                              </div>
                              <span></span>
                              <div className="specification">
                                <div>3</div>
                                <div>色</div>
                                <div>可</div>
                                <div>选</div>
                              </div>
                            </a>
                          </div>
                        )
                      })
                    ) : null
                  }
                  <div className="item swiper-slide more">
                    <a href="javascript:;" style={{display: 'block', width: '100%', height: '100%',}}>
                      <span className="text">查看全部</span>
                    </a>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <Split/>
        {/* 限时购 */}
        <LimitTimeBuy data={flashSaleIndexVO}/>
        <Split/>
        {/* 福利社 */}
        <Weal/>
        <Split/>
        {/* 专题精选 */}
        <div className="template">
          <header className="hd">
            <a className="more" href="javascript:;">
              <span>专题精选</span>
              <i className="icon icon-go"></i>
            </a>
          </header>
          <div className="indexTopics-slide">
            <div className="inner swiper-container homeCarousel-topic">
              <ul className="list swiper-wrapper">
                {
                  topicList ? (topicList.map(item => {
                      return (
                        <li className="item swiper-slide" key={item.id}>
                          <a className="imgWrap" href="javascript:;">
                            <img src={item.itemPicUrl} alt=""/>
                          </a>
                          <div className="line1">
                            <h4 className="title">{item.title}</h4>
                            <span className="price">{item.priceInfo}元起</span>
                          </div>
                          <div className="desc">{item.subtitle}</div>
                        </li>
                      )
                    })
                  ) : null
                }
              </ul>
            </div>
          </div>
        </div>
        <Split/>
        {/* 居家好物 */} {/* 遍历所有好物组件 */}
        {
          cateList ? (
            cateList.map(list => {
              return (
                <div key={list.id}>
                  <div className="template">
                    <div className="titleGoodGrid">
                      <h3 className="title">{list.name}好物</h3>
                      <div className="goodGrid">
                        <ul className="list">
                          {
                            list.itemList.slice(0, 7).map(item => {
                              return (
                                <li className="item" key={item.id}
                                    style={{
                                      zIndex: '6',
                                      padding: '0rem 0.26666666666666666rem 0.44rem 0.13333333333333333rem'
                                    }}>
                                  <a className="good" href="javascript:;">
                                    <div className="hd-jujia">
                                      <div className="wraper">
                                        <img
                                          src={item.listPicUrl}
                                          alt=""/>
                                        <div className="desc">{item.simpleDesc}</div>
                                      </div>
                                    </div>
                                    <div className="tagWrapper">
                                      <p className="status gradientPrice">{list.name}特惠</p>
                                    </div>
                                    <div className="name">
                                      <span>{item.name}</span>
                                    </div>
                                    <div className="newItemDesc">{item.simpleDesc}</div>
                                    <div className="price">
                                      <span>￥{item.retailPrice}</span>
                                    </div>
                                    <span></span>
                                    <div className="specification">
                                      <div>3</div>
                                      <div>色</div>
                                      <div>可</div>
                                      <div>选</div>
                                    </div>
                                  </a>
                                </li>
                              )
                            })
                          }
                          <li className="item item-more">
                            <a className="more moreH" href="javascript:;">
                              <p className="txt">更多{list.name}好物</p>
                              <i className="icon icon-goodGridMore"></i>
                            </a>
                          </li>
                        </ul>
                      </div>
                    </div>
                  </div>
                  <Split/>
                </div>
              )
            })
          ) : null
        }
        {/* 回到顶部 */}
        <GoTop isShow={isShow} scrollTop={scrollTop}/>
        {/* 底部导航栏 */}
        <FooterGuide/>
      </div>
    );
  }
}

// connect包装UI组件为容器组件
export default connect(
  // 更新获取状态
  state => ({homeData: state.homeData}),
  // 异步action，通知actions对象，发送ajax请求
  {getHomeData, getTopicData, getNavData}
)(Home)
<file_sep>/src/containers/shiwu/shiwuNavBanner/ShiwuNavBanner.jsx
/*
识物页面导航轮播图
 */

import React, {Component} from 'react'
import Swiper from 'swiper'

import './shiwuNavBanner.styl'

export default class ShiwuNavBanner extends Component {

  componentDidUpdate () {
    new Swiper('.swiper-container-banner2', {
      slidesPerView: 'auto',
      centeredSlides: false
    })
  }

  render () {
    const {column} = this.props
    return (
      <div className="exploreChannels">
        <div className="swiper-container-banner2">
          <div className="list swiper-wrapper">
            {
              column ? (
                column.map((item, index) => {
                  return (
                    <a className="item swiper-slide" key={index} href="javascript:;">
                      <div className="imgContainer channelPic"
                        style={{backgroundImage: 'url('+ item.picUrl +')'}}
                      ></div>
                      <div className="icon icon-rbGradient">
                        <p className="topNum">{item.articleCount}</p>
                      </div>
                      <div className="title">{item.title}</div>
                    </a>
                  )
                })
              ) : null
            }
          </div>
        </div>
      </div>
    )
  }
}
