React官方文档React理念Demo

最近准备系统学习React,首先看了官方文档,React官方中文文档,读到快速开始的React理念这一章,就动手写了一下Demo,按照提示实现了一遍,效果如下:
Github地址:https://lucyzlu.github.io/React-demo-product-list/my-app/build/index.html
JSFiddle:

width="100%" height="300" src="//jsfiddle.net/senmu/dz504L3L/6/embedded/" allowfullscreen="allowfullscreen">

下面提取官方文档中重要的点复制到此处,以及动手的过程中遇到的一些问题记录,最后贴上完整的HTML,CSS以及React+JSX源码以供参考。

1.功能和效果

提供的效果图如下,这是一个商品列表,上面的部分是对商品进行过滤搜索的交互区域,下面部分是根据用户的输入进行过滤后的商品列表展示。
React官方文档React理念Demo_第1张图片

如何进行组件化呢?
官方提供了如下的组件化划分方案:
React官方文档React理念Demo_第2张图片
在这里你会看到,我们的简单应用中有5个组件。我们把每个组件展示的数据用斜体表示。
React官方文档React理念Demo_第3张图片
组件层级可以表示成:
React官方文档React理念Demo_第4张图片
看起来很明了,那么就动手实现吧。我选择从底层组件开始写,一直写到顶层组件。

2.实现的步骤

整个步骤顺序:
第一步:把 UI 划分出组件层级

第二步:用 React 创建一个静态版本(也就是只在组件中只使用props进行单项数据流传递(不使用state),从父组件到子组件,并且在每个组件中使用render函数定义要渲染的UI,所有组件写好之后,为顶级组件提供一个数据看一下整个静态的UI是否正确)

第三步:定义 UI 状态的最小(但完整)表示(也就是确定有哪些state),考虑state时遵循如下3个问题:

  1. 它是通过 props 从父级传来的吗?如果是,他可能不是 state。
  2. 它随着时间推移不变吗?如果是,它可能不是 state。
  3. 你能够根据组件中任何其他的 state 或 props 把它计算出来吗?如果是,它不是 state。

第四步:确定你的 State 应该放在哪个组件中,遵循的4个问题如下:

  1. 确定每一个需要这个 state 来渲染的组件。
  2. 找到一个公共所有者组件(一个在层级上高于所有其他需要这个 state 的组件的组件)
  3. 这个公共所有者组件或另一个层级更高的组件应该拥有这个 state。
  4. 如果你没有找到可以拥有这个 state 的组件,创建一个仅用来保存状态的组件并把它加入比这个公共所有者组件层级更高的地方。

第五步:添加反向数据流(也就是向props中添加事件处理程序,触发父组件传递给子组件用于修改父组件中state的回调函数,注意这里每个组件只能直接修改存储在自己内部的state,调用this.setState()函数进行修改,并不能直接修改自己上级或者下级组件的state:当要修改自己上级组件的state时,可以调用上级组件通过props传递给自己的回调函数;对下级组件的数据传递通过props)

3.问题

实现的过程中遇到了两个问题,

1.JSX语法问题
一个是语法上面的问题,在定义ProductTable时使用了嵌套map函数,第一个map函数return的时候没有用一个顶级元素将其他元素包裹起来导致报错,因此:
map返回JSX的时候,要用一个顶级元素包裹起来,比如用tbody,否则会报错
一个table里可以有多个tbody标签

{this.props.categoryArray.map((item, index) => {
                    return (
                        
                            
                                "2">0].category} />
                            

                            {
                                item.map((line) => {
                                    if (line.name.toLowerCase().includes(this.props.filterText.toLowerCase())&&(this.props.onlyStocked?line.stocked:true)) {
                                        return ()
                                    } else {
                                        return null;
                                    }

                                })

                            }
                        
                    )
                })}

2.回调函数的this绑定(这一点理解很重要)
如下,当引擎调用onChange事件指定的事件处理程序时,该回调函数内部的this默认是指向undefined的,因此调用this.props时就会报错,不能调用undefined的属性,

class SearchBar extends React.Component {
    constructor(props) {
        super(props);
        this.handleInputChange = this.handleInputChange.bind(this);
    }

    handleInputChange(e) {
        const target = e.target;
        const value = target.type == "checkbox" ? target.checked : target.value;
        target.type == "checkbox" ? this.props.onCheckedChange(value) : this.props.onValueChange(value);
    }

    render() {
        return (
            <div className="searchBar">
                <div> "text" className="insetShadow" placeholder="Search..." value={this.props.search} value={this.props.search} onChange={this.handleInputChange} />div>
                <div>"checkbox" name="filter" checked={this.props.isChecked} onChange={this.handleInputChange} /> div>
            div>
        );
    }
}

解决办法之一是在constructor中使用bind函数显式绑定回调函数内的this。关于bind函数

3.数据结构问题
第三个问题是针对这个Demo的一个问题,就是展示商品列表的同时还要给同类的商品展示一个共同的类别名(也就是组件ProductCategoryRow),那么ProductCategoryRow要显示的Category名从何而来呢?观察一下JSON接口返回的数据:

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

我们可以将JSON数据进行改造,改成一个二维数组,二维数组的每个数组元素里的产品元素都具有相同的Category,那么展示的时候提取其第一个产品元素的Category就可以了,改造后的二维数据如下:

this.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" }]
        ];

4.源码

github源码:https://github.com/LucyZlu/React-demo-product-list

5.参考

React官方中文文档
bind应用场景和理解

你可能感兴趣的:(react)