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