• 从设计稿到实现React应用(分类数据处理)


    1. 确定设计稿和数据

    设计稿:

     数据:

    [
      {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"}
    ];

    2. 将设计稿UI分组件层级

    组件单一功能原则:

    即一个组件实现一个功能。

     图中,一个颜色是一种组件,按照嵌套关系,可以分为:

    FilterableProductTable:

       SearchBar:

       ProductTable:

           ProductCategoryRow

           ProductRow

    3. 确定需要的state值的个数

       原则:

    1. 值不是来自与props
    2. 值不是一成不变
    3. 值不能由其他state和props求得

    该示例中,需要数据源的地方有:

    1. 查询框的文本 // 会变化;state.filterText          
    2. 复选框的状态 // 会变化;state.isStock
    3. 所有的产品列表数据  // 通过props传入; 无state
    4. 过滤后的产品列表数据  //通过1,2,3获得; 无state

    4. 确定state的位置-状态提升

    通过分析state对应的值作用的范围,state应该位于所有作用区域的父组件;

    才能共享state。

    从功能分析,1,2的状态会影响列表展示;则其应该位于查询框和列表的父组件;

    即组件FilterableProductTable中。

    3的状态会影响列表分类ProductCategoryRow和列表项ProductRow,则应该放在他们的父组件;

    即组件ProductTable中。

    5. 添加反向数据流

    即通过触发子组件的事件监听,调用父组件传递过去的函数,从而改变父组件的state的值。

    因为state的状态提升,而state又是私有状态,只能通过state所处的组件的函数进行修改。

    6. 从下向上编写代码

    /*
     * @Author: LyraLee
     * @Date: 2019-11-08 09:01:58
     * @LastEditTime: 2019-11-20 17:32:14
     * @Description: 分类数据处理
     */
    'use strict'
    const products = [
      {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
      {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
      {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
      {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
      {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
      {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
    ];
    function ProductRow(props) {
      const product = props.product;
      const { name } = product;
      const renderName = !product.stocked ? <span style={{color: 'red'}}>{name}</span> : name
      return (
        <tr>
          <td>{renderName}</td>
          <td>{product.price}</td>
        </tr>
      )
    }
    function ProductCategoryRow(props) {
      const product = props.product;
      return(
        <tr>
          <th colSpan="2">{product.category}</th>
        </tr>
      )
    }
    function ProductTable(props) {
      const { filterText, isStockedOnly, products } = props;
      // 处理数据的方法!!!需要分类的属性是category,
      // 如果数据不是按照该属性排序,那先将其按照category的字段顺序
      let lastCategory = null;
      let rows = []
      products.sort((a,b) => a.category.localeCompare(b.category))
      .forEach(product => {
        if (!product.name.includes(filterText)) {
          return;
        }
        if (isStockedOnly && !product.stocked) {
          return;
        }
        if (product.category !== lastCategory) {
          rows.push(<ProductCategoryRow key={product.category} product={product} />)
        }
        rows.push(
          <ProductRow key={product.name} product={product} />
        )
        lastCategory = product.category;
      });
    
      return (
        <table>
          <thead>
            <tr>
              <th>name</th>
              <th>price</th>          
            </tr>
          </thead>
          <tbody>
            {rows}
          </tbody>
        </table>
      )
    }
    function SearchBar(props) {
      function handleChange (e) {
        const { name, type } = e.target;
        const value = type === 'checkbox' ? e.target.checked : e.target.value;
        props.handleChange(name, value);
      }
      const { filterText, isStockedOnly } = props; 
      return(
        <div>
          <input 
            name="filterText"
            type="text" 
            value={filterText} 
            onChange={handleChange}
            placeholder="search..."
          />
          <p>
            <input 
              name="isStockedOnly"
              type="checkbox"
              checked={isStockedOnly}
              onChange={handleChange}
            />{' '}
            Only show products in stock        
          </p>
        </div>
      )
    }
    class FileterableProductTable extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          filterText: '',
          isStockedOnly: false
        }
      }
      handleChange = (name, value) => {
        this.setState({
          [name]: value
        })
      }
      render() {
        const { filterText, isStockedOnly } = this.state;
        const { products } = this.props;
        return(
          <React.Fragment>
            <SearchBar
              filterText={filterText}
              isStockedOnly={isStockedOnly}
              handleChange={this.handleChange}
            />
            <ProductTable
              filterText={filterText}
              isStockedOnly={isStockedOnly}
              products={products}
            />
          </React.Fragment>
        )
      }
    }
    
    ReactDOM.render(<FileterableProductTable products={products} />, root); 
  • 相关阅读:
    MySQL的删除语句
    机器学习-K-means聚类及算法实现(基于R语言)
    机器学习-线性回归补充-实践
    什么是JWT
    Java的NIO
    音乐播放器歌词同步显示
    Linux和Mac下安装RocketMQ过程
    支付宝沙箱应用
    HTML5 调用手机摄像头拍照
    JavaWeb图片上传的几种方式
  • 原文地址:https://www.cnblogs.com/lyraLee/p/11899273.html
Copyright © 2020-2023  润新知