React组件进阶--组件通讯介绍,组件的 props特点,组件通讯的三种方式子到父,父到子,兄弟到兄弟组件,Context,回顾练习

1.组件通讯介绍

  • 组件是独立且封闭的单元,默认情况下,只能使用组件自己的数据(state)
  • 在组件化过程中,我们将一个完整的功能 拆分成多个组件,以更好的完成整个应用的功能。
  • 而在这个过程中,多个组件之间不可避免的要共享某些数据
  • 为了实现这些功能,就需要打破组件的独立封闭性,让其与外界沟通(为了能让各组件之间可以进行互相沟通,数据传递)。这个过程就是组件通讯。

2.组件的 props

每一个组件对象都有props;组件标签的所有的属性都保存到props中

1.组件是封闭的,

要接收外部数据应该通过 props 来实现

2.props的作用:

接收传递给组件的数据

3.传递数据:

给组件标签添加属性

 <Hello name="jack"/>

4.接收数据:

函数组件通过参数props接收数据。

//function Hello(props){
const Hello = (props) => {
  console.log(props)
  return (  
    <div>
      <h1>props:{props.name}</h1>
    </div>
    )
}

类组件通过 this.props 接收数据

class Hello extends React.Component {
  render() {
    console.log(this.props)
    return (
      <div>
        <h1>props:{this.props.name}</h1>
      </div>
    )
  }
}

1.通过this去访问props,需要在constructor进行接收,还需要在super(props)写props

class Counter extends React.Component {
   constructor(props) {
        super(props)       
        console.log(props)
        this.state = { Uname: this.props.name }
   }

   render () {
        console.log(this)//里面由props了,在render中可以直接通过this去访问props,而不需要像构造器一样
        return (
          <div>
             <h2>{this.state.Uname}</h2>
             <h1>{this.props.name}</h1>
          </div>
        )
   }
}

ReactDOM.render(<Counter name="xx" />, document.getElementById('root')); 

props的结果 

 

this的结果 

 

 

 2.果这个props里面还有对象的话,这样写就比较麻烦,可以通过解构进行简化

render () {
        const { name } = this.props
        return (
          <div>
            <h2>{this.state.Uname}</h2>
            <h1>{name}</h1>
          </div>
        )
}

3.批量操作

如果要传很多东西进去的话,可以把要传的值拿出来,单独书写。

  • {}:不是对象的意思,而是在里面要写js表达式
  • 如果传过去的是对象的话:data={data}

使用扩展运算符的话,就不需要多一个层级data

const data = { name: "xx", age: 10, sex: 'nan' }

ReactDOM.render(<Counter {...data} />, document.getElementById('root')); 

 

 传对象过去也可以,只不过会多一个层级data

render () {
     const { name, data } = this.props
     return (
          <div>
            <h1>{data.name}</h1>
          </div>
        )
    }
}
const data = { name: "xx", age: 10, sex: 'nan' }

ReactDOM.render(<Counter data={data} />, document.getElementById('root')); 

5.props是一个对象

6.传递非字符串的数据,需要加{ },

<Hello name="jack" age={19} />

7.可以传递数组,函数,JSX结构

<Hello 
      colors={['red', 'green']} 
      fn={() => console.log('object')} 
      tag={<p>xx</p>} />

3.组件的 props的特点

1.可以给组件传递任意类型的数据

数字、字符串、布尔值、数组、对象、函数、JSX

class App extends React.Component {
  state = {
    message: 'this is message'
  }
  render() {
    return (
      <div>
        <div>父组件</div>
        <FSon 
          msg={this.state.message} 
          age={20} 
          isMan={true} 
          cb={() => { console.log(1) }} 
          child={<span>this is child</span>}
        />
        <CSon msg={this.state.message} />
      </div>
    )
  }
}

  

2.props 是只读的对象(readonly),只能读取属性的值,无法修改对象

//根据单项数据流的要求,子组件只能读取props中的数据,不能进行修改
// 错误,不能直接进行修改
this.props.msg = 'new msg'

3.注意:

使用类组件时,如果写了构造函数,应该将 props 传递给 super(),

否则,无法在构造函数中获取到 props!

class Hello extends React.Component {
   // 推荐将props传递给父类构造函数
  constructor(props) {
    super(props) 
  }
  render() {
    return <div>接收到的数据:{this.props.age}</div> 
  } 
}

 演示代码

// 函数式Son
function Son (props) {
    // props:对象,里面存着通过父组件传入的所有数据[1,2,3]
    console.log(props)
    return (
        // 数组是用来遍历的,不是当成字符串渲<染的{props.list}
        <div>
            函数子组件:
            {props.list.map(item => <p key={item}>{item}</p>)}
            {props.userInfo.name}
            <button onClick={props.getMes}>
            触发父组件传入的函数
            </button>
            {props.child}
        </div>
    )
}

class App extends React.Component {
    state = {
        list: [1, 2, 3],
        userInfo: {
            name: 'zz',
            age: 11
        }
    }
    getMes = () => {
        console.log('父组件中的函数')
    }
    render () {
        return (
            <div>
                <Son
                    list={this.state.list}
                    userInfo={this.state.userInfo}
                    getMes={this.getMes}
                    child={<span>this is span</span>}
                />
            </div>
        )
    }
}

4.使用解构赋值

 const { list, userInfo, getMes, child } = props
    return (
        <div>
            函数子组件:
            {list.map(item => <p key={item}>{item}</p>)}
            {userInfo.name}
            <button onClick={getMes}>触发父组件传入的函数</button>
            {child}
        </div>
    )

第二种解构赋值---在参数上

function Son ({ list, userInfo, getMes, child }) {
    // const { list, userInfo, getMes, child } = props
    return (
        <div>
            函数子组件:
            {list.map(item => <p key={item}>{item}</p>)}
            {userInfo.name}
            <button onClick={getMes}>触发父组件传入的函数</button>
            {child}
        </div>
    )
}

这里写的就是原生的函数语法,props是一个普通的js对象---原生支持的写法,这里都是可以写的。

4.组件通讯的三种方式

组件之间的通讯分为 3 种:

  1. 父子关系 - 最重要
  2. 兄弟关系 - 自定义事件模式产生技术方法 eventBus / 通过共同的父组件通信
  3. 其它关系 - mobx / redux / 基于hook的方案

1.父组件 -> 子组件

实现父子通信中的父传子,把父组件中的数据传给子组件

通过props进行传值 

1.实现步骤 

1.父组件提供要传递的state数据

class Parent extends React.Component {
  state = {
    lastName: 'wang'
  }
}

2.给子组件标签添加属性,值为 state 中的数据

 <Child name={this.state.lastName}/>

3.子组件中通过 props 接收父组件中传递的数据

  1. 类组件使用this.props获取props对象
  2. 函数式组件直接通过参数获取props对象
const Child = (props) => {
  console.log('子组件:',props)
  return (
    <div className="child">
      <p>子组件,接收父组件的数据:{props.name}</p>
    </div>
  )
}

 

 完整代码

// 函数式子组件
function ASon(props) {
  // props:对象,里面存着通过父组件传入的所有数据。接收的是一个对象
  console.log(props)
  return (
    <div>
      子组件1
      {props.msg}
    </div>
)}

// 类子组件
class BSon extends React.Component {
  render() {
    return (
      <div>
        子组件2
        //类组件必须通过this关键词,去获取这里的props是固定的
        {this.props.msg}
      </div>
)}}

// 父组件
class App extends React.Component {
//通过props传递值给子组件
  state = {
    // 准备数据
    message: 'this is message'
  }
  render() {
    return (
      <div>
        <div>父组件</div>
        // 子组件身上绑定属性,属性名可以自定义,保持语义化
        <ASon msg={this.state.message} />
        <BSon msg={this.state.message} />
      </div>
)}}

2.子组件 -> 父组件

子传父:子组件调用父组件传递过来的函数,并且把想要传递的数据当作函数的实参传入

思路:利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数。父组件给子组件传递回调函数,子组件调用 

父组件将组件的某个方法传给子组件,子组件通过props接收到父组件传递过来的方法进行调用,并且将要传递的参数作为形参传递过去。

1.父组件提供一个回调函数(用于接收数据)

class Parent extends React.Component {
  getChlidMsg = data =>{
    console.log('接收到子组件中传递过来的数据:',data)
  }
}

2.将该函数作为属性的值,传递给子组件

<Child getMSg={this.getChlidMsg} />

3.子组件通过 props 调用回调函数

handleClick= () =>{
    // 子组件调用父组件中传递过来的回调函数 
    this.props.getMSg()
  }
  
{/* 绑定单击事件 */}
<button onClick={this.handleClick}>点击,给父组件传递数据</button>

4. 将子组件的数据作为参数传递给回调函数

state = {
   // 子组件传递数据
   msg:'xx'
 }
 // 子组件this.state.msg作为回调函数getMSg的参数,传递给父组件
this.props.getMSg(this.state.msg)

 5.父组件把数据展示在页面上

  • 提供父组件自己的状态

    state={
        parentMsg:''
      }
    
  • 打印状态的值

     父组件:{this.state.parentMsg}
    
  • 一开始时无显示的,拿到数据后,把parentMsg更新一下

     getChlidMsg = data => {
        this.setState({
          parentMsg:data
        })
      }
    

注意:回调函数中 this 指向问题

代码实现

一:

import React from 'react'

// 子组件,函数式Son
function Son(props) {
  function handleClick() {
    // 调用父组件传递过来的回调函数 并注入参数
    props.changeMsg('this is newMessage')
  }
  return (
    <div>
      {props.msg}
      <button onClick={handleClick}>change</button>
    </div>
  )
}
class App extends React.Component {
  state = {
    message: 'this is message'
  }
  // 提供回调函数
  //准备一个函数,传给子组件
  changeMessage = (newMsg) => {
    console.log('子组件传过来的数据:',newMsg)
    this.setState({
      message: newMsg
    })
  }
  render() {
    return (
      <div>
        <div>父组件</div>
        <Son
          msg={this.state.message}
          // 传递给子组件
          changeMsg={this.changeMessage}
        />
      </div>
)}}

export default App

 二:

// 函数式Son
function Son (props) {
    const { getSonMsg } = props
    function clickHandler () {
        const sonMsg = '来自子组件的数据'
        getSonMsg(sonMsg)
    }
    return (
        <div>
            this is son
            <button onClick={clickHandler}>click</button>
        </div>
    )
}
class App extends React.Component {
    // 1.准备一个函数,传给子组件
    getSonMsg = (sonMsg) => {
        console.log(sonMsg)
    }
    render () {
        return (
            <div>
                <Son getSonMsg={this.getSonMsg} />
            </div>
)}}

三: 

// 函数式子组件
function ASon (props) {
  return (
    <div>
      <h2>A组件</h2>
      <button onClick={() => { props.getChildrenValue('A组件传递过来的数据') }}>将数据传递给父组件</button>
    </div>
)}

// 类子组件
class BSon extends React.Component {
  state = { msg: 'B组件传递过来的数据' }
  render () {
    return (
      <div>
        <h2>B组件</h2>
        <button onClick={() => { this.props.getChildrenValue(this.state.msg) }}>将数据传递给父组件</button>
      </div>
)}}
// 父组件
class App extends React.Component {
  // 在父组件中定义一个方法,接收到参数的就是子组件传过来的参数
  getChildrenValue = (value) => {
    console.log(value)
    //做任意操作
    //更改状态
  }
  render () {
    return (
      <div>
        <h2>父组件</h2>
        <ASon getChildrenValue={this.getChildrenValue} />
        <BSon getChildrenValue={this.getChildrenValue} />
      </div>
)}}

四:如果放在不同的文件夹下 

App.js

import BSon from './Hello'

BSon.js 

import React from 'react'
// 类子组件
class BSon extends React.Component {
  state = { msg: 'B组件传递过来的数据' }
  render () {
    return (
      <div>
        <h2>B组件</h2>
        <button onClick={() => { this.props.getChildrenValue(this.state.msg) }}>将数据传递给父组件</button>
      </div>
)}}
// 导出组件
export default BSon

3.兄弟组件

核心思路:通过状态提升机制,利用共同的父组件实现兄弟通信

1.将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态

  • 提供共享状态
  • 提供操作共享状态的方法

2.思想:状态提升

3.公共父组件职责:1. 提供共享状态 2. 提供操作共享状态的方法

4.要通讯的子组件只需通过 props 接收状态或操作状态的方法

 

实现步骤

  1. 将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态(提供共享状态,提供操作共享状态的方法)
  2. 要接收数据状态的子组件通过 props 接收数据
  3. 要传递数据状态的子组件通过props接收方法,调用方法传递数据

 完整代码1

class Parent extends React.Component {
  // 提供共享状态
  state = {
    count: 0
  }

  // 提供修改状态的方法
  onIncrement = () => {
    this.setState({
      count: this.state.count + 1
    })
  }
  render() {
    return (
      <div>
        <Child1 count={this.state.count} />
        <Child2 onIncrement={this.onIncrement} />
      </div>
    )
  }
}

const Child1 = (props) => {
  return <h1>计数器:{props.count}</h1>
}

const Child2 = (props) => {
  // 一点击按钮,方法就会调用
  return <button onClick={() => props.onIncrement()}>+1</button>
}

 完整代码2

import React from 'react'

//目标:B组件中的数据传给A
// 技术方案:
// 1.先把B中的数据通过子传父,传给App
// 2.再把App接收到的Son中的数据,通过父传子 传给A

// 子组件A
function SonA(props) {
  return (
    <div>
      SonA
      {props.msg}
  -----------------------------------------------------------------    
      {props.sendMsg}
    </div>
)}
// 子组件B
function SonB(props) {
   const bMsg = '来自B组件的数据'
  return (
    <div>
      SonB
      <button onClick={() => props.changeMsg('new message')}>
        changeMsg
      </button>
  ------------------------------------------------------------------    
       <button onClick={() => props.getBMsg(bMsg)}>
        发送数据
       </button>
    </div>
)}

// 父组件
class App extends React.Component {
  // 父组件提供状态数据
  state = {
    message: 'this is message',
  ------------------------------------------------------------------
    sendMsg: '测试父传子初始值'
  }
  // 父组件提供修改数据的方法
  changeMsg = (newMsg) => {
    this.setState({
      message: newMsg
    })
  }
  ------------------------------------------------------------------
 // 声明一个传给B组件的方法
  getBMsg = (msg) => {
        console.log(msg)
        // 把msg数据交给sendMsg
        this.setState({
            sendMsg: msg
        })
  }
  render() {
    return (
      <>
        {/* 接收数据的组件 */}
        <SonA msg={this.state.message} />
        {/* 修改数据的组件 */}
        <SonB changeMsg={this.changeMsg} />
   -----------------------------------------------------------------
         <SonA sendMsg={this.state.sendMsg} />
         <SonB getBMsg={this.getBMsg} />
      </>
)}}

export default App

 类组件和函数组件传递案例:B传给A

// 函数式子组件A
function ASon (props) {
  return (
    <div>
      <h2>A组件</h2>
      <h3>B--{props.msgA}</h3>
    </div>
)}

// 类子组件B
class BSon extends React.Component {
  state = { msgB: 'B组件传递过来的数据' }
  render () {
    return (
      <div>
        <h2>B组件</h2>
        <button onClick={() => { this.props.getChildrenValue(this.state.msgB) }}>将数据传递给父组件</button>
      </div>
)}}

// 父组件
class App extends React.Component {
  state = { msg: '' }
  getChildrenValue = (value) => {
    console.log(value)
    this.setState({ msg: value })
  }
  render () {
    return (
      <div>
        <h2>父组件</h2>
        <ASon msgA={this.state.msg} />
        <BSon getChildrenValue={this.getChildrenValue} />
      </div>
)}}

案例:有一个文本框的组件,使用了两次,在一个文本框中输入内容的时候,另一个文本框也跟着一起动

// 类子组件
class BSon extends React.Component {
  // 4.子组件改变,将改变的值传入父组件 
  changeValue = (e) => {
    //5.通过调用父组件的方法
    this.props.getChildrenValue(e.target.value)
  }
  render () {
    return (
      <div>
        {/* props是单一性的 */}
        {/* 3.由父组件的状态来控制子组件的value值 */}
        <input type="text" onChange={this.changeValue} value={this.props.msg} />
      </div>
)}}

// 父组件
class App extends React.Component {
  // 1.状态提升:将共享的状态提升到共同的父组件中
  state = { msg: 'nihao' }
  getChildrenValue = (value) => {
    this.setState({ msg: value })
  }
  render () {
    return (
      <div>
        <h2>父组件</h2>
        {/* 虽然两个都是B,但是它们是单独的两个组件;现在想要他们成一个,即可以互相影响 */}
        <BSon msg={this.state.msg} getChildrenValue={this.getChildrenValue} />
        {/* 2.将共享的状态传给子组件 */}
        <BSon msg={this.state.msg} getChildrenValue={this.getChildrenValue} />
      </div>
)}}

5.跨组件通信Context

思考:App 组件要传递数据给 Child 组件,该如何处理?

处理方式:使用 props 一层层组件往下传递(繁琐)

更好的姿势:使用 Context。通过context api 实现跨组件通信

作用:跨组件传递数据(比如:主题、语言等)

 思考:想从App组件向任意一个下层组件传递数据,该怎么办呢?

 

目前我们能采取的方式就是一层一层的props往下传,显然很繁琐。

Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法

6.Context使用步骤

1.调用 React. createContext() 创建 Provider(提供数据) 和 Consumer(消费数据:要用数据的组件) 两个组件。

const { Provider, Consumer } = React.createContext()

2.使用 Provider 组件作为父节点(Provider包裹根组件提供数据)

<Provider>
 {/* 根组件 */}
  <div className="App">
    <Child1 />
  </div>
</Provider>
3.设置 value 属性,表示要传递的数据。
<Provider value="pink">

4.调用 Consumer 组件接收数据(需要用到数据的组件使用Consumer包裹获取数据)。

<Consumer>
 /* {value => /* 基于 context 值进行渲染*/} */
{data => <span>data参数表示接收到的数据 -- {data}</span>}
</Consumer>

完整代码

// 创建context得到两个组件
const { Provider, Consumer } = React.createContext()
// 函数组件
class App extends React.Component {
  render() {
    return (
      <Provider value="pink">
        <div className="app">
          <Node />
        </div>
      </Provider>
    )
  }
}

const Node = (props) => {
  return (
    <div className="node">
      <SubNode />
    </div>
  )
}

const SubNode = (props) => {
  return (
    <div className="subnode">
      <Child />
    </div>
  )
}

const Child = (props) => {
  return (
    <div className="child">
      <Consumer>
        {data => <span>data参数表示接收到的数据 -- {data}</span>}
      </Consumer>
    </div>
  )
}

 代码实现

App->A->C 变成 App->C

import React, { createContext }  from 'react'

// 1. 创建Context对象 
const { Provider, Consumer } = createContext()

// 3. 消费数据
function ComC() {
  return (
    <Consumer >
      {value => <div>{value}</div>}
    </Consumer>
  )
}

function ComA() {
  return (
    <ComC/>
  )
}

// 2. 提供数据
class App extends React.Component {
  
  state = {
    message: 'this is message'
  }
  render() {
    return (
      <Provider value={this.state.message}>
        <div className="app">
          <ComA />
        </div>
      </Provider>
    )
  }
}

export default App

步骤解析:

1.初始代码:

import React from "react"

// 函数式Son
function ComA (props) {
    return (
        <div>
            A
            <ComC />
        </div>
    )
}
function ComC (props) {
    return (
        <div>
            C
        </div>
    )
}

class App extends React.Component {
    // 1.准备一份数据
    state = {
        message: 'message'
    }
    render () {
        return (
            <div>
                <ComA />
            </div>
        )
    }
}

export default App

2.导入createContext方法并执行,解构提供者和消费者

import React,{createContext} from "react"

const {Provider,Consumer} = createContext()

3.App中,模板位置用Provider包裹根组件

<Provider value={this.state.message}>
  <div>
    <ComA />
  </div>
</Provider>

4.通过固定的value,把数据放过来

<Provider value={this.state.message}>

5.在ComC组件用Consumer包裹获取数据,通过Consumer使用数据

 <div>
  C
  <Consumer>
    {value => <span>{value}</span>}
  </Consumer>
</div>

不解构案例:

import React, { createContext } from 'react'
const Context = createContext()

class ASon extends React.Component {

  render () {
    return (
      <div>
        <BSon />
        //不单单时跨级通信
        <Context.Consumer>
          {value => <span>A组件{value}</span>}
        </Context.Consumer>
      </div>
)}}

class BSon extends React.Component {
  render () {
    return (
      <div>
        <h2>B组件</h2>
        <Context.Consumer>
          {value => <h2>App的数据{value}</h2>}
        </Context.Consumer>
      </div>
)}}

// 父组件
class App extends React.Component {
  state = { msg: 'nihao' }
  render () {
    return (
      <Context.Provider value={this.state.msg}>
        <div>
          <ASon />
        </div>
      </Context.Provider>
)}}

注意事项:

  1. 上层组件和下层组件关系是相对的,只要存在就可以使用,通常我们会通过app作为数据提供方。
  2. 这里涉及的语法都是固定的,
  3. 由两处提供的位置 value,提供数据
  4. 获取的位置 {value =>使用value做什么都可以}

总结:

  1. 如果两个组件是远方亲戚(比如,嵌套多层)可以使用Context实现组件通讯
  2. Context提供了两个组件:Provider 和 Consumer
  3. Provider组件:用来提供数据
  4. Consumer组件:用来消费数据

回顾练习

要求:App为父组件用来提供列表数据 ,ListItem为子组件用来渲染列表数据

// 列表数据
[
  { id: 1, name: '超级好吃的棒棒糖', price: 18.8, info: '开业大酬宾,全场8折' },
  { id: 2, name: '超级好吃的大鸡腿', price: 34.2, info: '开业大酬宾,全场8折' },
  { id: 3, name: '超级无敌的冰激凌', price: 14.2, info: '开业大酬宾,全场8折' }
]

1.完整代码

import React from 'react'

// 子组件
function ListItem(props) {
  const { name, price, info, id, delHandler } = props
  return (
    <div>
      <h3>{name}</h3>
      <p>{price}</p>
      <p>{info}</p>
      <button onClick={() => delHandler(id)}>删除</button>
    </div>
  )
}

// 父组件
class App extends React.Component {
  state = {
    list: [
      { id: 1, name: '超级好吃的棒棒糖', price: 18.8, info: '开业大酬宾,全场8折' },
      { id: 2, name: '超级好吃的大鸡腿', price: 34.2, info: '开业大酬宾,全场8折' },
      { id: 3, name: '超级无敌的冰激凌', price: 14.2, info: '开业大酬宾,全场8折' }
    ]
  }

  delHandler = (id) => {
    this.setState({
      list: this.state.list.filter(item => item.id !== id)
    })
  }

  render() {
    return (
      <>
        {
          this.state.list.map(item =>
            <ListItem
              key={item.id}
              {...item}
              delHandler={this.delHandler} 
            />
          )
        }
      </>
    )
  }
}

export default App

2.代码讲解

1.初始代码:

import React, { createContext } from "react"

// 渲染列表
function ListItem (props) {
    return (
        <div> 
        </div>
    )
}
// 数据提供者  渲染ListItem组件  App-ListItem
// 先不抽离组件,完成基础渲染后,再去抽离
class App extends React.Component {
    render () {
        return (
                <div>
                </div>
        )
    }
}

export default App

2.App中初始化list数据

state = {
        // 列表数据
        list: [
            { id: 1, name: '超级好吃的棒棒糖', price: 18.8, info: '开业大酬宾,全场8折' },
            { id: 2, name: '超级好吃的大鸡腿', price: 34.2, info: '开业大酬宾,全场8折' },
            { id: 3, name: '超级无敌的冰激凌', price: 14.2, info: '开业大酬宾,全场8折' }
        ]
}

3.UI部分

render () {
      return (
            <div>
                <h3>标题</h3>
                <p>价格</p>
                <p>说明</p>
                <button >删除</button>
           </div>
     )
}

4.遍历返回的结果

render () {
    return (
        <div>
           {this.state.list.map(item => (
             <>
                 <h3>标题</h3>
                 <p>价格</p>
                 <p>说明</p>
                 <button >删除</button>
             </>
          ))}
        </div>
   )
}

5.把渲染数据替换进去

 <h3>{item.name}</h3>
 <p>{item.price}</p>
 <p>{item.info}</p>

以上为不借助组件,完成的渲染

1.把以下部分变成组件,需要将其从App中移到ListItem中

 <h3>{item.name}</h3>
 <p>{item.price}</p>
 <p>{item.info}</p>
 <button >删除</button>

2.通过父传子,把ListItem传递到App父组件中

{this.state.list.map(item => <ListItem key={item.id}  item={item}/>)}

3.ListItem通过props接收数据

function ListItem ({item}) {

处理删除,需要用到子传父

4.添加绑定事件

delItem={this.delItem}

// 给子组件传递的函数
delItem=()=>{}

5.解构delItem,ListItem的button中添加点击事件,改造成箭头函数

function ListItem ({item,delItem}) {
    return (
        <div>
            <h3>{item.name}</h3>
            <p>{item.price}</p>
            <p>{item.info}</p>
            <button onClick={()=>delItem(item.id)}>删除</button>
        </div>
    )
}

6.delItem接收要删的id,删除操作

delItem = (id) => {
        this.setState({
            list: this.state.list.filter(item => item.id !== id)
        })
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值