React系列三 – 阶段案例练习

一. 书籍购物车说明

1.1. 案例介绍

现在我们来做一个相对综合一点的练习:书籍购物车;

案例效果如下:

案例效果

案例说明:

  • 1.在界面上以表格的形式,显示一些书籍的数据;

  • 2.在底部显示书籍的总价格;

  • 3.点击+或者-可以增加或减少书籍数量(如果为1,那么不能继续-);

  • 4.点击移除按钮,可以将书籍移除(当所有的书籍移除完毕时,显示:购物车为空~);

1.2. 项目的搭建

这里,我们使用React将默认的数据先展示出来:



  
  
  Document

  
    table {
      border: 1px solid #e9e9e9;
      border-collapse: collapse;
    }

    td, th {
      border: 1px solid #e9e9e9;
      padding: 8px 16px;
    }

    th {
      background-color: #f7f7f7;
      color: #5c6b77;
    }

    .counter {
      margin: 0 5px;
    }
  


    
  
class App extends React.Component { constructor(props) { super(props); this.state = { books: [ { id: 1, name: '《算法导论》', date: '2006-9', price: 85.00, count: 1 }, { id: 2, name: '《UNIX编程艺术》', date: '2006-2', price: 59.00, count: 1 }, { id: 3, name: '《编程珠玑》', date: '2008-10', price: 39.00, count: 1 }, { id: 4, name: '《代码大全》', date: '2006-3', price: 128.00, count: 1 }, ] } } render() { const { books } = this.state; return (
{ books.map((item, index) => { return ( ) }) }
书籍名称 出版日期 价格 购买数量 操作
{index + 1} {item.name} {item.date} {"¥" + item.price} {item.count}
) } } ReactDOM.render(, document.getElementById("app"));

二. 书籍购物车功能

1.1. 价格的显示

我们可以封装一个工具函数,用于格式化价格:

function formatPrice(price) {
  if (typeof price !== "number") {
    price = Number(price) || 0;
  }
  return "¥" + price.toFixed(2);
}

对之前显示的价格进行格式化:

{formatPrice(item.price)}

封装一个App中的方法,用于获取商品总价格显示的内容:

getTotalPrice() {
  let totalPrice = 0;
  for (let book of this.state.books) {
    totalPrice += book.count * book.price
  }
  return "总价格:" + formatPrice(totalPrice);
}

使用一个h2元素显示总价格:

{this.getTotalPrice()}

1.2. 数量的变化

封装一个方法,用于改变书籍的数量:

  • 注意:在React中,要保证数据的不可变性;

  • 所以,我们是先复制一份books,对其进行修改,再通过setState更新到最新的状态;

changeItem(index, counter) {
  const books = [...this.state.books];
  this.setState({
    books: books.map((item, indey) => {
      if (indey == index) {
        item.count += counter;
      }
      return item;
    })
  })
}

修改jsx对应位置的代码:


  <button disabled={item.count  this.changeItem(index, -1)}>-
  {item.count}
  

1.3. 移除的操作

封装一个方法,用于移除对应的书籍:

removeItem(index) {
  const books = [...this.state.books];
  this.setState({
    books: books.filter((item, indey) => index !== indey)
  })
}

修改对应的移除jsx代码:


如果所有的书籍移除完毕,那么要显示购物车为空:

  • 封装两个方法,一个用于获取显示购物车的jsx代码(后期会封装成一个组件),一个用于获取显示购物车为空的jsx代码(后期也可以封装为一个组件)

renderBooks() {
  const { books } = this.state;
  return (
    
{ books.map((item, index) => { return ( ) }) }
书籍名称 出版日期 价格 购买数量 操作
{index + 1} {item.name} {item.date} {formatPrice(item.price)} {item.count}

{this.getTotalPrice()}

) } renderEmpty() { return

购物车为空~

}

重新编写render方法代码:

render() {
  const { books } = this.state;
  return books.length ? this.renderBooks() : this.renderEmpty();
}