typescript編寫react組件3 —— 購物車計數組件

前言

接上一篇文章的代碼片斷,今天爲你們提供另外一組件——購物車計數,由於當初寫組件時沒有想到會有多複雜,因此寫到後面才發現整個組件存在大的問題,開篇就不提bug在哪裏了,結尾告訴你們,不過有興趣的小夥伴們能夠重構整個組件,能夠聯繫我,咱們一塊兒來討論。數據結構

組件結構

/*
 * ShopCarTable
 *    ProductTable
 *        ProductRow
 *            ProductCount
 *        ProductTotal
 */

代碼片斷

interface Product {
  id: string,
  name: string,
  price: number
}
interface ProductCount {
  pid: string,
  count: number
}

// ProductCount
interface ProductCountProps {
  onCount: (c: number) => any;
  count: number;
}
interface ProductCountState {

}
class ProductCountEditor extends React.Component<ProductCountProps, ProductCountState>{
  handleClickAdd = () => this.props.onCount(this.props.count + 1)
  handleClickRed = () => this.props.count > 0 && this.props.onCount(this.props.count - 1)
  public render() {
    return (
      <form>
        <input type="button" value="-" onClick={this.handleClickRed} />
        <input type="text" value={this.props.count + ''} readOnly />
        <input type="button" value="+" onClick={this.handleClickAdd} />
      </form>
    );
  }
}
// ProductRow
interface ProductRowProps {
  product: Product
  count: number
  onCount: (c:number)=>void
}
class ProductRow extends React.Component<ProductRowProps, {}>{
  constructor(props: any) {
    super(props);
  }
  public render() {
    const {id, name, price} = this.props.product
    const count = this.props.count
    return (
      <tr>
        <td>{id}</td>
        <td>{name}</td>
        <td>{price}¥</td>
        <td><ProductCountEditor count={count} onCount={this.props.onCount} /></td>
        <td>{price * count}¥</td>
      </tr>
    );
  }
}

// ProductTotal
interface ProductTotalProps {
  total: number
}
function ProductTotal(props: ProductTotalProps) {
  return (
    <tfoot>
      <tr>
        <td colSpan={5}>總價: {props.total}¥</td>
      </tr>
    </tfoot>
  );
}

// ProductTable
interface ProductTableProps {
  products: Product[]
}
interface ProductTableState {
  counts: ProductCount[]
}
class ProductTable extends React.Component<ProductTableProps, ProductTableState>{
  constructor(props: ProductTableProps) {
    super(props);
    let counts: ProductCount[] = props.products.map(p => ({pid: p.id, count: 0}));
    this.state = { counts };
  }
  public render() {
    const products = this.props.products;
    const counts = this.state.counts;
    let productNodes = products.map(p => {
      let c = counts.filter(c => c.pid===p.id)[0];
      return (
        <ProductRow key={p.id} product={p} count={c.count} onCount={count => {
          let countsSlice = counts.slice();
          console.log(countsSlice);
          countsSlice.splice(counts.indexOf(c), 1, {pid:c.pid, count});
          this.setState({ counts: countsSlice });
        }} />
      );
    });
    return (
      <table>
        <thead>
          <tr>
            <th>產品id</th>
            <th>產品名稱</th>
            <th>產品單價</th>
            <th>產品數量</th>
            <th>產品總計</th>
          </tr>
        </thead>
        <tbody>
          {productNodes}
        </tbody>
        <ProductTotal total={this.state.counts.map(pc => {
          return this.props.products.filter(p => p.id === pc.pid)[0].price * pc.count
        }).reduce((sum,c)=>sum+c, 0)} />
      </table>
    );
  }
}

let PRODUCTS: Product[] = [
  { id: '1', name: '揹包', price: 49.99 },
  { id: '2', name: '衣服', price: 34 }
];

ReactDOM.render(
  <ProductTable products={PRODUCTS} />,
  document.getElementById('example')
);

結尾

你們發現這個大問題是什麼了嗎?
是個人數據結構一開始就沒有定義好,因此個人計數實現才那麼複雜。之後數據最好改爲適合本身應用的結構。。。就像這個組件中,products跟counts沒有組合在一塊兒就很不方便了。
下面是實現的效果:圖片描述this

相關文章
相關標籤/搜索