react文档demo实现输入展示搜索结果列表
文档页面地址:https://doc.react-china.org/docs/thinking-in-react.html
该文档只给了具体实现思路,下面是我实现的代码。
初学react,如果有写的不规范的地方,望大家多多指正!
FilterableProductTable (橙色): 包含了整个例子
SearchBar (蓝色): 接受所有的用户输入
ProductTable (绿色): 根据用户输入过滤并展示数据集合
ProductCategoryRow (绿松石色): 展示每个分类的标题
ProductRow (红色): 用行来展示每个产品
文档中清楚的为我们划分出了具体组件模块,各个组件实现如下:
App.js
import React from 'react'; import ReactDOM from 'react-dom'; import FilterableProductTable from './FilterableProductTable' ReactDOM.render( <FilterableProductTable/>, document.getElementById('root') );
FilterableProductTable.js
import React from 'react' import SearchBar from './SearchBar' import ProductTable from './ProductTable' /* * 需要定义的state或值: *原产品列表 *用户输入的搜索文本 *复选框的值 * 需要根据以上值计算的值: *产品的筛选列表 */ const data=[ {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"} ]; class FilterableProductTable extends React.Component{ constructor(props){ super(props); this.state = { filterText: '', inStockOnly: true, list:data }; this.handleSearch=this.handleSearch.bind(this); this.handleCheckBox=this.handleCheckBox.bind(this); } handleSearch(keywods){ this.setState({ filterText:keywods }); } handleCheckBox(checkBoxStatus){ this.setState({ inStockOnly:checkBoxStatus }); } render(){ const filterText=this.state.filterText; const inStockOnly=this.state.inStockOnly; const list=this.state.list; return( <div> <SearchBar filterText={filterText} inStockOnly={inStockOnly} onSearch={this.handleSearch} list={list} onCheckBox={this.handleCheckBox}/> <ProductTable filterText={filterText} inStockOnly={inStockOnly} list={list} /> </div> ) } } export default FilterableProductTable
SearchBar.js:
import React from 'react' class SearchBar extends React.Component{ constructor(props){ super(props); this.handleChange=this.handleChange.bind(this); this.checkboxChange=this.checkboxChange.bind(this); } handleChange(e){ e.preventDefault(); let inputText=this.refs.inputText.value; this.props.onSearch(inputText); } checkboxChange(e){ // let checkboxStatus=this.refs.checkbox.checked; 通过ref获取 let checkboxStatus=e.target.checked; //通过event.target事件获取 this.props.onCheckBox(checkboxStatus); } render(){ return( <div> <input type="text" ref='inputText' value={this.props.filterText} onChange={this.handleChange} placeholder="输入产品名称"/> <div> <input type="checkbox" ref="checkbox" checked={this.props.inStockOnly} onChange={this.checkboxChange}/> 仅仅展示有库存的商品 </div> </div> ) } } export default SearchBar
ProductTable.js:
import React from 'react' import ProductCategoryRow from './ProductCategoryRow' import ProductRow from './ProductRow' class ProductTable extends React.Component{ /* constructor(props){ super(props); }*/ render(){ let filterText=this.props.filterText; let inStockOnly=this.props.inStockOnly; let curCategory=""; return( <table> <thead> <tr style={{fontWeight:'bold'}}> <td>Name</td> <td>Price</td> </tr> </thead> {this.props.list.map((value,index) => { let listItemShow; if(value.name.toLowerCase().indexOf(filterText.toLowerCase())!==-1||filterText===''){ listItemShow=true; if(inStockOnly===true&&value.stocked===true){ listItemShow=true; }else if(inStockOnly===true&&value.stocked===false){ listItemShow=false; } }else{ listItemShow=false; } let categoryStatus=false; if(value.category===curCategory){ categoryStatus=false; }else{ categoryStatus=true; } curCategory=value.category; return ( <tbody key={index}> <ProductCategoryRow category={value.category} categoryStatus={categoryStatus}/> <ProductRow stocked={value.stocked} name={value.name} price={value.price} show={listItemShow}/> </tbody> ) }) } </table> ) } } export default ProductTable
ProductCategoryRow.js
import React from 'react' class ProductCategoryRow extends React.Component{ /*constructor(props){ super(props); }*/ render(){ let styleObj = { display : this.props.categoryStatus ? 'block':'none', fontWeight:"bold" }; return( <tr style={styleObj}> <td> {this.props.category} </td> </tr> ) } } export default ProductCategoryRow
ProductRow.js
import React from 'react' class ProductRow extends React.Component{ /*constructor(props){ super(props); }*/ render(){ let styleObj = { display : this.props.show ? 'block':'none', }; return ( <tr style={styleObj}> <td> {this.props.name} </td> <td> {this.props.price} </td> </tr> ) } } export default ProductRow
总结:react 的state要定义在几个组件的公共父组件上,这里定义在最外层的 FilterableProductTable.js 组件上,修改state 即setState也在定义state的组件上操作,所有修改的方法通过传入子组件,子组件通过props获得该方法,把改变之后的值传入父组件,即实现了父子组件数据的双向传递。
github源文件:https://github.com/beileixinqing/react-doc-demo-search