18. react - 父子组件传参

1. 父组件传递给子组件

  通过 props 传递数据(状态,方法)

2. 子组件 -> 父组件

  通过props传递给子组件方法,子组件通过 this.props.func 调用父组件方法改变父组件状态。

  不同于 VUE 没有 emit。

3. 使用消息订阅模式 兄弟组件之间传参 pubsub-js

  npm i --save pubsub-js

  import pubSUb from 'pubsub-js'

  // 发布

  pubSub.publish('eventName', 参数)

  // 订阅

  pubSub.subscribe('eventName', (msg, data)=> {})

  

4. 实例:

  父组件: simpleCart.js

  子组件:Cart.js

  

// simpleCart.js

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

export default class CartSample extends React.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})
    }
    
    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})
    }
    render() {
        return (
            <div style={cartStyle}>
                {/* 事件处理 */}
                <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} countChange={this.countChange}></Cart>
            </div>
        );
    }
}

const cartStyle = {
    border: '1px solid #ddd',
    marginTop: '50px',
    background: 'rgba(80, 255, 20, 0.6)'
}

 

//Cart.js

import React from 'react';

class Cart extends React.Component {
    constructor (props) {
        super(props)
    }

    

    render () {
        return (
            <table>
                <tbody>
                {
                    this.props.list.map((item, i) => (
                        <tr key={i}>
                            <td>名称:{item.name}</td>
                            <td>数量:
                                <button onClick={() => this.props.countChange(item)}>-</button>
                                    {item.count}
                                <button onClick={() => this.props.countChange(item,1)}>+</button>
                            </td>
                        </tr>
                    ) )
                }
                </tbody>
            </table>
        )
    }
}

export default Cart

 

posted @ 2020-10-28 10:15  monkey-K  阅读(599)  评论(0编辑  收藏  举报