react product details page, shopping cart logic, Raja uploaded on the home page, down to refresh

1 Review

2. Click on the list to enter the product details page

  • Design-layout documents to the structure of the page layout, design details page entry
// index.js 入口文件
import Detail from '@/Detail';
<Route path="/d">
  <Detail />
</Route>
// Detail.js 布局文件
import React from 'react';
// 一种布局有很多的页面 --- Switch
import { Switch, Route } from 'react-router-dom';
import Detail from '@/views/detail';
// 布局找页面
function App() {
  return (
    <Switch>
      <Route path="/d/detail" component = { Detail } />
    </Switch>
  );
}

export default App;

// views/detail/index.jsx
import React, { Component } from 'react';

class Detail extends Component {

  render () {
    return (
      <div className="container">
        <div className="box">
          <header className="header">详情头部</header>
          <div className="content">
            详情内容
          </div>
        </div>    
        <footer className="footer">
          详情底部
        </footer>
      </div>
    )
  }
}

export default Detail

2.1 Declarative jump to the details page

Modify the route, add the parameter src / Detail.js layout file

<Switch>
  <Route path="/d/detail/:proid" component = { Detail } />
</Switch>

Hit the jump list of components --- Link ---- /components/Prolist/index.jsx

<Link to={ '/d/detail/' + item.proid } className="proitem" key = { item.proid }>
  <div className="proimg">
    <img src={ item.proimg } alt="" />
  </div>
  <div className="proinfo">
    { item.proname }
  </div>
</Link>
  • Interface design utils request details / api.js
/**
 * 获取详情页面的数据
 * @param {*} type 
 */
const getDetailData = (proid) => {
  return new Promise(resolve => {
    request.get('/pro/detail', { params: { proid }}).then(res => {
      resolve(res.data)
    })
  })
}

// 3、暴露接口
export {
  getProlist,
  getBannerlist,
  getCartlist,
  login,
  getDetailData // ++++++++++++++++++++++++
}
  • Details page to obtain data
import React, { Component } from 'react';
import { getDetailData } from '@/utils/api'
class Detail extends Component {
  constructor(props) {
    super(props);
    this.state = { // +++++++++++++++
      proname: '',
      proimg: ''
    }
  }

  componentDidMount () { // +++++++++++++++++++++++
    // console.log(this.props)
    let proid = this.props.match.params.proid
    getDetailData(proid).then(data => {
      this.setState({
        proname: data.data.proname,
        proimg: data.data.proimg
      })
    })
  }

  render () {
    return (
      <div className="container">
        <div className="box">
          <header className="header">详情头部</header>
          <div className="content">
            <img src={ this.state.proimg } alt=""/>
            <p>{ this.state.proname }</p>
          </div>
        </div>    
        <footer className="footer">
          详情底部
        </footer>
      </div>
    )
  }
}

export default Detail

2.2 Programmatic jump to the details page

components / Prolist / index.jsx normal to add a click event, did not get into the history of this property

If the route has nothing to do with the inner component (page to find components), passing parameters history when the page calling component, or is passed directly to the component this.props

// views/home/index.jsx
<Prolist prolist = { this.state.prolist } history = { this.props.history } { ...this.props }/>

App.js change the layout of the page is called the way

<Switch>
  <Route path = "/home" component = { Home }/>
  <Route path = "/kind" component = { Kind }/>
  <Route path = "/cart" component = { Cart }/>
  <Route path = "/user" component = { User }/>
  {
    //<Route path = "/user"><User /></Route>
  }
</Switch>
  • List jump components / Prolist / index.jsx
<li onClick= { () => {
  console.log(this.props)
  // ++++++++++++++++++++++++++
  this.props.history.push('/d/detail/' + item.proid)
}} className="proitem" key = { item.proid }>
  <div className="proimg">
    <img src={ item.proimg } alt="" />
  </div>
  <div className="proinfo">
    { item.proname }
  </div>
</li>

3, Add to Cart

  • Add to Cart Interface Design utils / api.js
/**
 * 加入购物车
 * @param {*} type 
 */
const addCart = (userid, proid, num) => {
  return new Promise(resolve => {
    request.get('/cart/add', { params: { userid, proid, num } }).then(res => {
      resolve(res.data)
    })
  })
}

// 3、暴露接口
export {
  getProlist,
  getBannerlist,
  getCartlist,
  login,
  getDetailData,
  addCart //+++++++++++++++++
}
  • For more details, click on the Add to Cart, call interface
<footer className="footer">
  <Button type="primary" onClick = { () => {
    let userid = localStorage.getItem('userid');
    let proid = this.state.proid;
    let num = 1;
    addCart(userid, proid, num).then(data => {
      if (data.code === '10119') {
        Toast.fail('还未登陆', 1);
        this.props.history.push('/o/login')
      } else {
        Toast.success('加入购物车成功', 1);
      }
    })
  }}>加入购物车</Button>
</footer>
  • Modify the server authentication token routing
    day05 / app.js

4, 404 and redirect

  • The first to write a 404 page views / notfound / index.jsx
import React from 'react';

class Com extends React.Component {
  render () {
    return (
      <div className="box">
        <header className="header">404头部</header>
        <div className="content">404内容</div>
      </div>
    )
  }
}

export default Com;
  • Modify App.js - exact route must be current route
<Switch>
  <Route path = "/home" component = { Home }/>
  <Route path = "/kind" component = { Kind }/>
  <Route path = "/cart" component = { Cart }/>
  <Route path = "/user" component = { User }/>
  <Redirect from="/" exact to="/home"/>
  <Route component = { NotFound } />
</Switch>

5, View Cart

import React from 'react';
import { getCartlist } from '@/utils/api';
import { Link } from 'react-router-dom';
class Com extends React.Component {
  constructor (props) {
    super(props);
    this.state = {
      cartlist: [],
      flag: false, // 是不是有数据
    }
  }
  componentDidMount () {
    console.log('222222222')
    getCartlist(localStorage.getItem('userid')).then(data => {
      console.log(data)
      if (data.code === '10119') { // 有没有登陆
        this.props.history.push('/o/login')
      } else if (data.code === '11000'){ // 有没有数据
        this.setState({
          flag: false
        })
      } else {
        this.setState({
          flag: true,
          cartlist: data.data
        })
      }
    })
  }
  render () {
    return (
      <div className="box">
        <header className="header">购物车头部</header>
        <div className="content">
          {
            this.state.flag ? 
            <ul>
              {
                this.state.cartlist.map((item, index) => {
                  return (
                    <li key={ item.cartid }>
                      <img src={ item.proimg } alt=""/>
                      { item.proname } --- { item.price }
                    </li>
                  )
                })
              }
            </ul>
            : <div>购物车空空如也,<Link to="/home">请购物</Link></div>
          }
        </div>
      </div>
    )
  }
}

export default Com;
  • Calculate the total price and the total number of
import React from 'react';
import { getCartlist } from '@/utils/api';
import { Link } from 'react-router-dom';
class Com extends React.Component {
  constructor (props) {
    super(props);
    this.state = {
      cartlist: [],
      flag: false, // 是不是有数据
      totalNum: 0, // ++++++++++++++++++++++
      totalPrice: 0 // +++++++++++++++++++++
    }
  }
  componentDidMount () {
    console.log('222222222')
    getCartlist(localStorage.getItem('userid')).then(data => {
      console.log(data)
      if (data.code === '10119') { // 有没有登陆
        this.props.history.push('/o/login')
      } else if (data.code === '11000'){ // 有没有数据
        this.setState({
          flag: false
        })
      } else {
        this.setState({
          flag: true,
          cartlist: data.data
        })
        this.getTotal() // ++++++++++++++++++++
      }
    })
  }
  // 计算总价以及总数量 ++++++++++++++++++++++++++
  getTotal () {
    console.log(3333)
    let totalNum = 0
    let totalPrice = 0
    this.state.cartlist.map(item => {
      totalNum += item.num
      totalPrice += item.num * item.price
    })
    this.setState({
      totalNum,
      totalPrice
    })
  }
  render () {
    return (
      <div className="box">
        <header className="header">购物车头部</header>
        <div className="content">
          {
            this.state.flag ? 
            <ul>
              {
                this.state.cartlist.map((item, index) => {
                  return (
                    <li key={ item.cartid }>
                      <img src={ item.proimg } alt=""/>
                      { item.proname } --- { item.price }
                      <button>-</button> { item.num } <button>+</button>
                    </li>
                  )
                })
              }
            </ul>
            : <div>购物车空空如也,<Link to="/home">请购物</Link></div>
          }
          <div>总数:{ this.state.totalNum }</div>
          <div>总价:{ this.state.totalPrice }</div>
        </div>
      </div>
    )
  }
}

export default Com;
  • Subtract the number of shopping cart data
import React from 'react';
import { getCartlist, updateCart } from '@/utils/api';
import { Link } from 'react-router-dom';
class Com extends React.Component {
  constructor (props) {
    super(props);
    this.state = {
      cartlist: [],
      flag: false, // 是不是有数据
      totalNum: 0,
      totalPrice: 0
    }
  }
  componentDidMount () {
    console.log('222222222')
    getCartlist(localStorage.getItem('userid')).then(data => {
      console.log(data)
      if (data.code === '10119') { // 有没有登陆
        this.props.history.push('/o/login')
      } else if (data.code === '11000'){ // 有没有数据
        this.setState({
          flag: false
        })
      } else {
        this.setState({
          flag: true,
          cartlist: data.data
        })
        this.getTotal()
      }
    })
  }
  // 计算总价以及总数量
  getTotal () {
    console.log(3333)
    let totalNum = 0
    let totalPrice = 0
    this.state.cartlist.map(item => {
      totalNum += item.num
      totalPrice += item.num * item.price
      return 0
    })
    this.setState({
      totalNum,
      totalPrice
    })
  }

  add (index, num) {
    // 1、获取列表
    let cartlist = this.state.cartlist;
    // 2、获取加的这个产品 ---- 根据索引值
    let obj = cartlist[index];
    num++;
    // 3、调用接口

    updateCart(obj.cartid, num).then(data => {
      if (data.code === '10119') {
        this.props.history.push('/o/login')
      } else if (data.code === '11111'){ // 数据库数量更新成功
        console.log('update success')
        // 更新本地的数据
        cartlist[index].num = num
        this.setState({ // 重新渲染视图
          cartlist
        })
        this.getTotal()
      }
    })
  }

  reduce (index, num) {
    // 1、获取列表
    let cartlist = this.state.cartlist;
    // 2、获取加的这个产品
    let obj = cartlist[index];
    if(num <= 1) {
      num = 1
      return  // 代码不继续往下执行
    } else {
      num--
    }
    // 3、调用接口

    updateCart(obj.cartid, num).then(data => {
      if (data.code === '10119') {
        this.props.history.push('/o/login')
      } else if (data.code === '11111'){
        console.log('update success')
        cartlist[index].num = num
        this.setState({
          cartlist
        })
        this.getTotal()
      }
    })
  }
  render () {
    return (
      <div className="box">
        <header className="header">购物车头部</header>
        <div className="content">
          {
            this.state.flag ? 
            <ul>
              {
                this.state.cartlist.map((item, index) => {
                  return (
                    <li key={ item.cartid }>
                      <img src={ item.proimg } alt=""/>
                      { item.proname } --- { item.price }
                      <button onClick={ this.reduce.bind(this, index, item.num)}>-</button> { item.num } <button onClick={ this.add.bind(this, index, item.num) }>+</button>
                    </li>
                  )
                })
              }
            </ul>
            : <div>购物车空空如也,<Link to="/home">请购物</Link></div>
          }
          <div>总数:{ this.state.totalNum }</div>
          <div>总价:{ this.state.totalPrice }</div>
        </div>
      </div>
    )
  }
}

export default Com;
  • Delete cart
import React from 'react';
import { getCartlist, updateCart, deleteCart } from '@/utils/api';
import { Link } from 'react-router-dom';
class Com extends React.Component {
  constructor (props) {
    super(props);
    this.state = {
      cartlist: [],
      flag: false, // 是不是有数据
      totalNum: 0,
      totalPrice: 0
    }
  }
  componentDidMount () {
    console.log('222222222')
    getCartlist(localStorage.getItem('userid')).then(data => {
      console.log(data)
      if (data.code === '10119') { // 有没有登陆
        this.props.history.push('/o/login')
      } else if (data.code === '11000'){ // 有没有数据
        this.setState({
          flag: false
        })
      } else {
        this.setState({
          flag: true,
          cartlist: data.data
        })
        this.getTotal()
      }
    })
  }
  // 计算总价以及总数量
  getTotal () {
    console.log(3333)
    let totalNum = 0
    let totalPrice = 0
    this.state.cartlist.map(item => {
      totalNum += item.num
      totalPrice += item.num * item.price
      return 0
    })
    this.setState({
      totalNum,
      totalPrice
    })
  }

  add (index, num) {
    // 1、获取列表
    let cartlist = this.state.cartlist;
    // 2、获取加的这个产品 ---- 根据索引值
    let obj = cartlist[index];
    num++;
    // 3、调用接口

    updateCart(obj.cartid, num).then(data => {
      if (data.code === '10119') {
        this.props.history.push('/o/login')
      } else if (data.code === '11111'){ // 数据库数量更新成功
        console.log('update success')
        // 更新本地的数据
        cartlist[index].num = num
        this.setState({ // 重新渲染视图
          cartlist
        })
        this.getTotal()
      }
    })
  }

  reduce (index, num) {
    // 1、获取列表
    let cartlist = this.state.cartlist;
    // 2、获取加的这个产品
    let obj = cartlist[index];
    if(num <= 1) {
      num = 1
      return  // 代码不继续往下执行
    } else {
      num--
    }
    // 3、调用接口

    updateCart(obj.cartid, num).then(data => {
      if (data.code === '10119') {
        this.props.history.push('/o/login')
      } else if (data.code === '11111'){
        console.log('update success')
        cartlist[index].num = num
        this.setState({
          cartlist
        })
        this.getTotal()
      }
    })
  }

  del (index) {
    // 1、获取列表
    let cartlist = this.state.cartlist;
    // 2、获取加的这个产品
    let obj = cartlist[index];

    deleteCart(localStorage.getItem('userid'), obj.proid).then(data => {
      if(data.code === '10119') {
        this.props.history.push('/o/login')
      } else if (data.code === '11110') {
        cartlist.splice(index, 1)
        console.log(cartlist)
        this.setState({
          cartlist
        })
        this.getTotal()
      }
    })
  }

  render () {
    return (
      <div className="box">
        <header className="header">购物车头部</header>
        <div className="content">
          {
            this.state.flag ? 
            <ul>
              {
                this.state.cartlist.map((item, index) => {
                  return (
                    <li key={ item.cartid }>
                      <img src={ item.proimg } alt=""/>
                      { item.proname } --- { item.price }
                      <button onClick={ this.reduce.bind(this, index, item.num)}>-</button> { item.num } <button onClick={ this.add.bind(this, index, item.num) }>+</button>
                      <button onClick= { this.del.bind(this, index) }>删除</button>
                    </li>
                  )
                })
              }
            </ul>
            : <div>购物车空空如也,<Link to="/home">请购物</Link></div>
          }
          <div>总数:{ this.state.totalNum }</div>
          <div>总价:{ this.state.totalPrice }</div>
        </div>
      </div>
    )
  }
}

export default Com;
  • select
import React from 'react';
import { getCartlist, updateCart, deleteCart } from '@/utils/api';
import { Link } from 'react-router-dom';
class Com extends React.Component {
  constructor (props) {
    super(props);
    this.state = {
      cartlist: [],
      flag: false, // 是不是有数据
      totalNum: 0,
      totalPrice: 0,
      all: true
    }
  }
  componentDidMount () {
    console.log('222222222')
    getCartlist(localStorage.getItem('userid')).then(data => {
      console.log(data)
      if (data.code === '10119') { // 有没有登陆
        this.props.history.push('/o/login')
      } else if (data.code === '11000'){ // 有没有数据
        this.setState({
          flag: false
        })
      } else {
        data.data.map(item => {
          item.checked = true
          return 0
        })
        this.setState({
          flag: true,
          cartlist: data.data
        })
        this.getTotal()
      }
    })
  }
  // 计算总价以及总数量
  getTotal () {
    console.log(3333)
    let totalNum = 0
    let totalPrice = 0
    this.state.cartlist.map(item => {
      if (item.checked) {
        totalNum += item.num
        totalPrice += item.num * item.price
      } else {
        totalNum += 0
        totalPrice += 0
      }
      return 0
    })
    this.setState({
      totalNum,
      totalPrice
    })
  }

  add (index, num) {
    // 1、获取列表
    let cartlist = this.state.cartlist;
    // 2、获取加的这个产品 ---- 根据索引值
    let obj = cartlist[index];
    num++;
    // 3、调用接口

    updateCart(obj.cartid, num).then(data => {
      if (data.code === '10119') {
        this.props.history.push('/o/login')
      } else if (data.code === '11111'){ // 数据库数量更新成功
        console.log('update success')
        // 更新本地的数据
        cartlist[index].num = num
        this.setState({ // 重新渲染视图
          cartlist
        })
        this.getTotal()
      }
    })
  }

  reduce (index, num) {
    // 1、获取列表
    let cartlist = this.state.cartlist;
    // 2、获取加的这个产品
    let obj = cartlist[index];
    if(num <= 1) {
      num = 1
      return  // 代码不继续往下执行
    } else {
      num--
    }
    // 3、调用接口

    updateCart(obj.cartid, num).then(data => {
      if (data.code === '10119') {
        this.props.history.push('/o/login')
      } else if (data.code === '11111'){
        console.log('update success')
        cartlist[index].num = num
        this.setState({
          cartlist
        })
        this.getTotal()
      }
    })
  }

  del (index) {
    // 1、获取列表
    let cartlist = this.state.cartlist;
    // 2、获取加的这个产品
    let obj = cartlist[index];

    deleteCart(localStorage.getItem('userid'), obj.proid).then(data => {
      if(data.code === '10119') {
        this.props.history.push('/o/login')
      } else if (data.code === '11110') {
        cartlist.splice(index, 1)
        console.log(cartlist)
        this.setState({
          cartlist
        })
        this.getTotal()
      }
    })
  }
  // 全选
  selectAll () {
    let cartlist = this.state.cartlist;
    let all = this.state.all
    all = !all
    cartlist.map(item => {
      item.checked = all
      return 0
    })
    this.setState({
      cartlist,
      all
    })
    this.getTotal()
  }
  // 单选
  seletceItem (index) {
    let cartlist = this.state.cartlist;
    // 点击切换当前的选择框
    cartlist[index].checked = !cartlist[index].checked;

    if (cartlist[index].checked) {
      let flag = cartlist.every(item => { // 所有的值都为true
        return item.checked === true
      })
      if (flag) {
        this.setState({
          all: true,
          cartlist
        })
      } else {
        this.setState({
          all: false,
          cartlist
        })
      }
    } else {
      this.setState({
        all: false,
        cartlist
      })
    }
    this.getTotal()
  }
  render () {
    return (
      <div className="box">
        <header className="header">购物车头部</header>
        <div className="content">
          {
            this.state.flag ? 
            <ul>
              {
                this.state.cartlist.map((item, index) => {
                  return (
                    <li key={ item.cartid }>
                      <input type="checkbox" onChange={ this.seletceItem.bind(this, index)} checked={item.checked}/>
                      <img src={ item.proimg } alt=""/>
                      { item.proname } --- { item.price }
                      <button onClick={ this.reduce.bind(this, index, item.num)}>-</button> { item.num } <button onClick={ this.add.bind(this, index, item.num) }>+</button>
                      <button onClick= { this.del.bind(this, index) }>删除</button>
                    </li>
                  )
                })
              }
            </ul>
            : <div>购物车空空如也,<Link to="/home">请购物</Link></div>
          }
          <div><input type="checkbox" checked = { this.state.all } onChange = { this.selectAll.bind(this) }/> 全选</div>
          <div>总数:{ this.state.totalNum }</div>
          <div>总价:{ this.state.totalPrice }</div>
        </div>
      </div>
    )
  }
}

export default Com;

6, pull down to refresh the home side and the LAC upload

cnpm i react-pullload -S

  • In the introduction page at
import ReactPullLoad, { STATS } from "react-pullload";
import "react-pullload/dist/ReactPullLoad.css";
  • The constructor adds variables
constructor (props) {
  super(props);
  this.state = {
    bannerlist: [{ bannerid: 1, img: 'images/1.jpg'}],
    prolist: [],
    hasMore: true, // 上拉加载时还有没有更多的数据 ++++++++++++++++
    action: STATS.init, // 下拉刷新和上拉加载的状态 ++++++++++++
    pageCode: 1 // 页码 +++++++++++++++++++
  }
}
  • Use the component package contents
<ReactPullLoad
    downEnough={150}
    ref="reactpullload"
    isBlockContainer={true}
    action={this.state.action}
    handleAction={this.handleAction.bind(this)}
    hasMore={this.state.hasMore}
    distanceBottom={100}
  >
  <ul></ul>
</ReactPullLoad>

render () {
    return (
      <div className="box">
        <header className="header">首页头部</header>
        <div className="content">
        <ReactPullLoad
            downEnough={150}
            ref="reactpullload"
            isBlockContainer={true}
            action={this.state.action}
            handleAction={this.handleAction.bind(this)}
            hasMore={hasMore}
            distanceBottom={100}
          >
          <Carousel
            autoplay={ true }
            infinite
            beforeChange={(from, to) => console.log(`slide from ${from} to ${to}`)}
            afterChange={index => console.log('slide to', index)}
          >
            {this.state.bannerlist.map(item => (
              <a
                key={ item.bannerid }
                href="https://www.baidu.com"
                style={{ display: 'inline-block', width: '100%', height: '176px' }}
              >
                <img
                  src={`http://47.92.152.70/${item.img}`}
                  alt=""
                  style={{ width: '100%', verticalAlign: 'top' }}
                  onLoad={() => {
                    // fire window resize event to change height
                    window.dispatchEvent(new Event('resize'));
                    this.setState({ imgHeight: 'auto' });
                  }}
                />
              </a>
            ))}
          </Carousel>
          <Prolist prolist = { this.state.prolist } history = { this.props.history } { ...this.props }/>
          </ReactPullLoad>
        </div>
      </div>
    )
  }
  • Achieve slip events handleAction
handleAction (action) {
    console.info(action, this.state.action, action === this.state.action);
    //new action must do not equel to old action
    if (action === this.state.action) { // 如果状态并且发生改变
      return false;
    }

    if (action === STATS.refreshing) { // 如果用户在下拉并且触发了更新的条件
      //刷新
      this.handRefreshing(); // 下拉刷新函数
    } else if (action === STATS.loading) { // 上拉加载条件成立
      //加载更多
      this.handLoadMore(); // 上拉加载函数
    } else {
      //DO NOT modify below code
      this.setState({ // 其他状态
        action: action
      });
    }
  };
  • Show drop-down refresh and upload function on Raja
handLoadMore () {

}

handRefreshing () {}
  • Raja uploaded on
handLoadMore () {
    if (STATS.loading === this.state.action) { // 如果正在加载数据
      return false;
    }
    //无更多内容则不执行后面逻辑
    if (!this.state.hasMore) {
      return;
    }
    // 设置为加载状态
    this.setState({
      action: STATS.loading
    });
    // 获取页码
    let pageCode = this.state.pageCode
    // 请求数据
    getProlist(pageCode).then(data => {
      let more = data.data.length === 0 // 还有没有数据
      pageCode++
      if (more) { // 没有数据了
        this.setState({
          action: STATS.reset, // 重置action,重置状态
          hasMore: false // 没有数据了
        });
      } else {
        this.setState({
          prolist: [...this.state.prolist, ...data.data], // 先合并在赋值
          action: STATS.reset, // 重置状态
          pageCode: pageCode // 重置页码
        })
        console.log(this.state.prolist)
      }
    })
  }
  • Pull down to refresh
handRefreshing () {
    if (STATS.refreshing === this.state.action) { //如果正在刷新
      return false;
    }
    this.setState({ // 设置为刷新状态
      action: STATS.refreshing
    });
    // 请求数据
    getProlist().then(data => {
      this.setState({
        prolist: data.data, //默认数据
        hasMore: true, // 代表可以请求下一页数据
        action: STATS.refreshed // 重置当前状态
      })
    })
    
  };

Modify Style to modify test.scss

Guess you like

Origin www.cnblogs.com/hy96/p/11893302.html