React實現購物車功能

可能不是蘋果發表於2016-11-01

這個簡單的demo,功能是這樣的:
最左側是列表,點選列表項可檢視詳情,中間是詳情,詳情中有按鈕,點選可加入購物車,最右側是購物車,購物車自動更新總數和總價.
使用create-react-app建立.
程式碼如下:

index.js:

import React from `react`;
import ReactDOM from `react-dom`;
import Books from `./Books`;
import `../node_modules/bootstrap/dist/css/bootstrap.min.css`;
import `./styles/index.css`;

ReactDOM.render(
  <Books />,
  document.getElementById(`root`)
);

Books.js:

import React, { Component } from `react`;

import BookList from `./BookList`;
import BookDetail from `./BookDetail`;
import Car from `./Car`;

class Books extends Component {
  constructor() {
    super()
    this.handleListClick = this.handleListClick.bind(this);
    this.handleAddToCar = this.handleAddToCar.bind(this);

    this.state = {
      currentBook: null,
      car: [],
      totalNum: 0,
      total: 0
    };
  }

  handleListClick(book) {
    this.setState({
      currentBook: book
    });
  }

  handleAddToCar(currentBook) {
    let totalNum = this.state.totalNum;
    let car = this.state.car;
    let total = this.state.total;

    let exist = false;

    if (car.length) {
      car.forEach(book => {
        if (book.id === currentBook.id) {
          book.number += 1;
          totalNum += 1;
          exist = true;
          this.setState({
            totalNum
          });
        }
      });
    }

    if (!exist) {
      car = car.concat(Object.assign({}, currentBook, {number:1}));
      totalNum += 1;
      this.setState({
          car,
          totalNum
      }); 
    }

    total = car.map(book => (book.price * book.number)).reduce((prev, cur) => prev + cur);
    this.setState({
      total
    });
  }

  render() {
    return (
      <div className=`row`>
        <BookList books={this.props.books} listClick={this.handleListClick}/>
        <BookDetail currentBook={this.state.currentBook} addToCar={this.handleAddToCar}/>
        <Car {...this.state} />
      </div>
    );
  }
}

Books.defaultProps = {
    books: [
    {
      id: 1,
      category: `CSS`,
      title: `CSS權威指南`,
      author: `Eric A. Meyer`,
      price: 42
    },
    {
      id: 2,
      category: `JS`,
      title: `JavaScript高階程式設計`,
      author: `Nicholas C.Zakas`,
      price: 69
    },
    {
      id: 3,
      category: `CSS`,
      title: `精通CSS:高階Web標準解決方案`,
      author: `巴德,科利森,莫爾`,
      price: 25
    }
  ]
};

export default Books;

BookList.js:

import React from `react`;

const BookList = ({books, listClick}) => {
  return (
    <div className=`col-md-2`>
      <h2>圖書列表</h2>
        <ul>
          {books.map((book) => {
            return (
              <li key={book.id} onClick={() => listClick(book)}>
                {book.title}
              </li>
            )            
          })}
        </ul>
    </div>
  );
};

export default BookList;

BookDetail.js

import React from `react`;

const Bookdetail = ({currentBook, addToCar}) => {
  if (!currentBook) return <div className=`col-md-4`><h2>選擇圖書</h2></div>
  return (
    <div className=`col-md-4`>
      <h2>圖書詳情</h2>
      <h3>{currentBook.title}</h3>
      <p>作者:{currentBook.author}</p>
      <p>價格:{currentBook.price}</p>
      <p>編號:{currentBook.id}</p>
      <button onClick={() => addToCar(currentBook)}>
        放進購物車
      </button>
    </div>
  );
};

export default Bookdetail;

Car.js:

import React from `react`;

const Car = ({car, totalNum, total}) => {
  let result = car.length ? <p>共{totalNum}本 總價為{total}</p>: <p>購物車為空</p>;
  return (
    <div className=`col-md-6`>
      <h2>購物車</h2>
      <ul>
        {
          car.map((book, index) => {
            return <li key={index}>
              {book.title} 價格為: {book.price} 已選擇{book.number}本
            </li>
          })
        }
      </ul>
      {result}
    </div>
  );
};

export default Car;

相關文章