假设我们已经有了一个返回 JSON 的 API
[
{category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
{category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
{category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
{category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
{category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
{category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
];
我们的应用中包含五个组件
FilterableProductTable (橙色): 是整个示例应用的整体
SearchBar (蓝色): 接受所有的用户输入
ProductTable (绿色): 展示数据内容并根据用户输入筛选结果
ProductCategoryRow (天蓝色): 为每一个产品类别展示标题
ProductRow (红色): 每一行展示一个产品
最终的效果
在这里插入图片描述
import React from 'react';
import { Component } from 'react';
import ReactDom from 'react-dom';
class ProductCategoryRow extends Component {
render() {
const category = this.props.category
return (
<tr>
<th colSpan='2'>
{category}
</th>
</tr>
)
}
}
class ProductRow extends Component {
render() {
const product = this.props.product;
const name = product.stocked ? product.name : <span style={{ color: 'red' }}> {product.name}</span>
return (
<tr>
<td>{name}</td>
<td>{product.price}</td>
</tr>
)
}
}
class ProductTable extends Component {
render() {
const filterText = this.props.filterText;
const inStockOnly = this.props.inStockOnly;
const rows = [];
let lastCategory = null;
this.props.products.forEach(product => {
if(product.name.indexOf(filterText)===-1){
return;
}
if(inStockOnly&&!product.stocked){//等会重新在看下这里的逻辑,还有上面的东西
return;
}
if (product.category !== lastCategory) {
rows.push(
<ProductCategoryRow category={product.category} key={product.category} />
)
}
rows.push(
<ProductRow product={product} key={product.name} />
)
lastCategory = product.category;
});
return (
<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
);
}
}
class SearchBar extends Component {
constructor(props){
super(props);
this.handleFilterTextChange = this.handleFilterTextChange.bind(this);
this.handleInStockChange = this.handleInStockChange.bind(this);
}
handleFilterTextChange(e){
this.props.onFilterTextChange(e.target.value);
}
handleInStockChange(e){
this.props.onInStockChange(e.target.value);
}
render() {
const filterText = this.props.filterText;
const inStockOnly = this.props.inStockOnly;
return (
<from>
<input type='text' placeholder="Search..." value = {filterText} onChange = {this.handleFilterTextChange} />
<p>
<input type='checkbox' checked= {inStockOnly} onChange = {this.handleInStockChange} />
{' '}
Only show products in stock
</p>
</from>
)
}
}
class FilterableProductTable extends Component {
constructor(props) {
super(props);
this.state = {
filterText: '',
inStockOnly: false
}
this.handleFilterTextChange = this.handleFilterTextChange.bind(this);
this.handleInStockChange = this.handleInStockChange.bind(this);
}
handleFilterTextChange(filterText){
this.setState({
filterText:filterText
})
}
handleInStockChange(inStockOnly){
this.setState({
inStockOnly:inStockOnly
})
}
render() {
return (
<div>
<SearchBar filterText={this.state.filterText} inStockOnly={this.state.inStockOnly} onFilterTextChange={this.handleFilterTextChange} onInStockChange={this.handleInStockChange} />
<ProductTable products={this.props.products} filterText={this.state.filterText} inStockOnly={this.state.inStockOnly} />
</div>
)
}
}
const PRODUCTS = [
{ category: 'Sporting Goods', price: '$49.99', stocked: true, name: 'Football' },
{ category: 'Sporting Goods', price: '$9.99', stocked: true, name: 'Baseball' },
{ category: 'Sporting Goods', price: '$29.99', stocked: false, name: 'Basketball' },
{ category: 'Electronics', price: '$99.99', stocked: true, name: 'iPod Touch' },
{ category: 'Electronics', price: '$399.99', stocked: false, name: 'iPhone 5' },
{ category: 'Electronics', price: '$199.99', stocked: true, name: 'Nexus 7' }
];
ReactDom.render(
<FilterableProductTable products={PRODUCTS} />, document.getElementById('root')
)