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