接上一篇文章的代碼片斷,今天爲你們提供另外一組件——購物車計數,由於當初寫組件時沒有想到會有多複雜,因此寫到後面才發現整個組件存在大的問題,開篇就不提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