React communication component Paternity

In this article we learn to communicate between components, continue to add more articles and display of goods mentioned in the list as an example, its complex functions into a small shopping cart case that split a cart list of subcomponents to communicate with the cart parent component.

Parent component subassembly to the traditional values, traditional values ​​by props

1. In src -> components folder, create a new sub-assembly Cart.js , we create a value-based subassemblies pass over the class, the parent component by this.props call, the specific code as follows:

import React, { Component } from 'react';
// 基于类的组件
export default class Cart extends Component {
    render() {
        return (
            <table>
                <tbody>
                    {this.props.list.map(item  => (
                        <tr key={item.id}>
                            <td>名称:{item.name}</td>
                            <td>数量:{item.count}</td>
                        </tr>
                    ))} 
                </tbody>
            </table>
        );
    }
}

The above code we give is based on components by value of the class, if you are more accustomed to the type of function to create components that use the value of the property can be directly passed over in the function, the specific code as follows:

import React, { Component } from 'react';
//  函数类型的组件
export function Cart({list}){
    return (
        <table>
            <tbody>
                {list.map(item  => (
                <tr key={item.id}>
                    <td>名称:{item.name}</td>
                    <td>数量:{item.count}</td>
                </tr>
                ))} 
            </tbody>
        </table> 
    )
}

2. Open the src -> components -> CartSample.js files on import step to create Cart components, and by props traditional values, while the new increase in the commodity purchase button column, click on Add to Cart to achieve results, and show the page, specific code to achieve the following:

import React, { Component } from 'react';
// 基于类的组件 导入方式
import Cart from './Cart';
// 函数类型的组件 导入方式
// import { Cart } from './Cart';

export default class CartSample extends Component {
    //  状态的初始化一般放在构造器中
    constructor(props){
        super(props);
        this.state = {
            text: '',
            goods: [],
            cartList: []
        }
        this.textChange = this.textChange.bind(this)
    }
    // 当 input 的值 text 发生变化的时候,我们让 textChang 去切换 input 的值
    textChange (event){
        this.setState({text: event.target.value})
    }
    addGoods = () => {
        this.setState(prevstate => {
            // react 官方希望传入与返回的对象不应该是同一个对象
            return {
                goods: [
                    ...prevstate.goods,
                    {
                        id: prevstate.goods.length + 1,
                        name: prevstate.text
                    }
                ]
            }
        })
    }
    // 加购
    addToCart = (good) => {
        // 创建一个新的购物车列表
        const newCartList = [ ...this.state.cartList ]
        // 根据 商品ID 判断购物车内有无传入的商品
        const idx = newCartList.findIndex( c => c.id === good.id)
        // 找到该 idx 对应的商品 
        const item = newCartList[idx]
        if(item){
            // 如果购物车内有该商品,则商品数量 +1
            // 删除 idx 项,再新增一项,新增项的属性和 item 一样,唯独修改 count
            newCartList.splice(idx,1,{ ...item,count: item.count +1 })
        }else{
            // 如果购物车内没有该商品
            newCartList.push({...good,count:1})
        }
        //更新
        this.setState({cartList:newCartList})
    }
    render() {
        return (
            <div>
                {/* 事件处理 */}
                <div>
                    <input type="text" value={this.state.text} onChange={this.textChange}/> 
                    <button onClick={this.addGoods}>加入商品</button>
                </div>
                <h1>商品列表</h1>
                <ul>
                   {this.state.goods.map((good) => (
                       <li key={good.id}> 
                            {good.name} 
                            {/* 新增 加购按钮 */}
                            <button onClick={() => this.addToCart(good)}>加入购物车</button>
                        </li>
                   ))}
                </ul>
                {/* 购物车 */}
                <h1>购物车列表</h1>
                 {/* 通过 list 属性吧购物车列表传给 cart 组件 */}
                <Cart list={this.state.cartList}></Cart>
            </div>
        );
    }
}

Subassembly to the traditional values ​​parent component

In React neutron component wants to pass the value of parent element is the parent element a callback function passed directly through the subassembly way property, called lift state, i.e. the state of the sub-assembly lifted out, distributed to the parent component, telling sub-assemblies which function to call when the data changes, then how to achieve it?
1. Continue with the above code, for example, the new sub-assembly can add and subtract the number of items of demand, it requires us to modify sub-assemblies Cart.js code, the number of count new front and rear label - and + buttons , the original tr tag code read as follows:

<td>名称:{item.name}</td>
<td>数量:
    <button onClick={() => minus(item)}>-</button>
        {item.count}
    <button onClick={() => add(item)}>+</button>
</td>

2. Open the src -> components -> CartSample.js file, modify the following code in the code on the basis of the original:

// 新增函数,处理数量的更新
add = (good) =>{
    const newCartList = [ ...this.state.cartList ]
    const idx = newCartList.findIndex( c => c.id === good.id)
    const item = newCartList[idx]
    // 点击 + 按钮其实就是购物车内有该商品,然后该商品数量 +1
    newCartList.splice(idx,1,{ ...item,count: item.count +1 })
    this.setState({cartList:newCartList})
}
minus = (good) =>{
    const newCartList = [ ...this.state.cartList ]
    const idx = newCartList.findIndex( c => c.id === good.id)
    const item = newCartList[idx]
    // 点击 + 按钮其实就是购物车内有该商品,然后该商品数量 -1
    newCartList.splice(idx,1,{ ...item,count: item.count -1 })
    this.setState({cartList:newCartList})
}

{/* 原本 cart 标签新增 add 和 minus 属性 */}
<Cart list={this.state.cartList} add={this.add} minus={this.minus}></Cart>

In fact, there are a lot of duplicate code above, can be optimized, we do look at the following optimization:

// Cart.js 中修改 + - 按钮的点击事件
<td>数量:
    <button onClick={() => this.props.countChange(item)}>-</button>
        {item.count}
    <button onClick={() => this.props.countChange(item,1)}>+</button>
</td>

// CartSample.js 中删除 add 和 minus 函数,新增 countChange
countChange = (good,type) =>{
    const newCartList = [ ...this.state.cartList ]
    const idx = newCartList.findIndex( c => c.id === good.id)
    const item = newCartList[idx]
    // 购物车列表中肯定有该商品,因为不需要判断 item 是否存在,只需要对 count 进行操作即可 
    if(type){// 有 type 即是 点击 + 按钮,商品数量 +1
        newCartList.splice(idx,1,{ ...item,count: item.count +1 })
    }else{ // 否则就是点击 - 按钮,商品数量 -1
        newCartList.splice(idx,1,{ ...item,count: item.count -1 })
    }
    this.setState({cartList:newCartList})
}
{/* 删除 add 和 minus 函数,新增 countChange 的属性*/}
<Cart list={this.state.cartList} countChange={this.countChange}></Cart>

Guess you like

Origin www.cnblogs.com/-muzi/p/11964825.html