1

前言

接上一篇文章的代码片段,今天为大家提供另一组件——购物车计数,因为当初写组件时没有想到会有多复杂,所以写到后面才发现整个组件存在大的问题,开篇就不提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没有组合在一起就很不方便了。
下面是实现的效果:图片描述


xingqiwu
220 声望18 粉丝

茫茫人海中,茫茫地走着···