面试题:react

父子组件通讯

1. 父传子通过props

父组件:

import React, { Component } from 'react'
import Navbar from './Navbar'
export default class App extends Component {
 render () {
   return (
     <div>
       <Navbar title="我是导航栏"></Navbar>
     </div>
  )
 }
}

子组件Navbar

import React, { Component } from 'react'
import ReactPropTypes from 'prop-types'
export default class Navbar extends Component {
 render () {
   let { title } = this.props
   return (
     <div>{title}</div>
   )
 }
}
Navbar.propTypes = {
 title: ReactPropTypes.string
}

2. 子传父通过调用父组件传过来的方法(也是通过props传)

父组件:

import React, { Component } from 'react'
import Test from './test'
export default class App extends Component {
 state = {
   num: 0
 }

 render () {
   return (
     <div>
       {this.state.num}
       <Test addNum={() => {
         this.add()
       }}></Test>
     </div>
   )
 }
 add () {
   this.setState({
     num: this.state.num + 1
   })
 }
}

子组件:

import React, { Component } from 'react'

export default class Test extends Component {
 render () {
   return (
     <div>
      <button onClick={this.props.addNum}>+1</button>
    </div>
   )
 }
}

3. 子组件是非受控组件,父组件通过ref获取子组件的一切信息和方法从而控制子组件并获取子组件当前的state(一般适用于表单域子组件)

非父子组件通讯

1. 状态提升(中间人模式)

Ract中的状态提升慨括来说,就是将多个组件需要共享的状态提升到它们最近的父组件上。在父组件上改变这个状态然后通过props分发给子组件。
在这里插入图片描述

import React, { Component } from 'react'
import axios from 'axios'
export default class App extends Component {
  state = {
    filmList: [],
    info: ''
  }
  constructor() {
    super()
    axios.get('http://localhost:3000/filmList.json').then(res => {
      console.log(res.data.data.films)
      this.setState({
        filmList: res.data.data.films
      })
    })
  }
  refreshInfo (val) {
    this.setState({
      info: val
    })
  }
  render () {
    return (
      <div>
        <h1>电影列表</h1>
        <div>
          {
            this.state.filmList.map(item => {
              return <FilmItem key={item.filmId} {...item} onEvent={(val) => this.refreshInfo(val)}></FilmItem>
            })
          }
        </div>
        <Info info={this.state.info}></Info>
      </div>
    )
  }
}


class FilmItem extends Component {
  render () {
    let { name, synopsis, poster } = this.props
    return <div style={{ borderBottom: '1px solid black', width: '200px' }} onClick={() => {
      this.props.onEvent(synopsis)
    }}>
      <h3>{name}</h3>
      <img src={poster} alt="" style={{ height: '50px', width: '50px' }} />
    </div>
  }
}

class Info extends Component {
  render () {
    let { info } = this.props
    return <div style={{ position: 'fixed', top: '50px', right: '50px', width: '300px', height: '300px', background: 'yellow' }}>{info}</div>
  }
}

2. 发布订阅模式

订阅者订阅某个第三方的内容,就是把一个能够改变订阅者自身状态的回调函数传给了第三方平台,每次当发布者发布内容时都会通知第三方平台,然后第三方平台对所有的回调函数进行调用(等同于通知了订阅者相关信息)

import React, { Component } from 'react'
import axios from 'axios'

let bus = {
  callbackList: [],
  // 订阅
  subscribe (callback) {
    this.callbackList.push(callback)
  },
  // 发布
  publish (val) {
    this.callbackList.forEach(callback => {
      callback && callback(val)
    })
  }
}

export default class App extends Component {
  state = {
    filmList: [],
  }
  constructor() {
    super()
    axios.get('http://localhost:3000/filmList.json').then(res => {
      this.setState({
        filmList: res.data.data.films
      })
    })
  }

  render () {
    return (
      <div>
        <h1>电影列表</h1>
        <div>
          {
            this.state.filmList.map(item => {
              return <FilmItem key={item.filmId} {...item} ></FilmItem>
            })
          }
        </div>
        <Info></Info>
      </div>
    )
  }
}


class FilmItem extends Component {
  render () {
    let { name, synopsis, poster } = this.props
    return <div style={{ borderBottom: '1px solid black', width: '200px' }} onClick={() => {
      bus.publish(synopsis)
    }}>
      <h3>{name}</h3>
      <img src={poster} alt="" style={{ height: '50px', width: '50px' }} />
    </div>
  }
}

class Info extends Component {
  state = {
    info: ''
  }
  constructor() {
    super()
    bus.subscribe((val) => {
      this.setState({
        info: val
      })
    })
  }
  render () {
    return <div style={{ position: 'fixed', top: '50px', right: '50px', width: '300px', height: '300px', background: 'yellow' }}>
      {this.state.info}
    </div>
  }
}

3. context状态树传参

import React, { Component } from 'react'
import axios from 'axios'

// 创建context
let GlobalContext = React.createContext()

export default class App extends Component {
  state = {
    filmList: [],
    info: ''
  }
  constructor() {
    super()
    axios.get('http://localhost:3000/filmList.json').then(res => {
      this.setState({
        filmList: res.data.data.films
      })
    })
  }

  render () {
    return (
      <GlobalContext.Provider value={{
        info: this.state.info,
        changeInfo: (info) => {
          // 必须通过setState方法去触发父组件的render函数重新执行,进而让子组件也执行更行
          this.setState({
            info
          })
        }
      }}>
        <div>
          <h1>电影列表</h1>
          <div>
            {
              this.state.filmList.map(item => {
                return <FilmItem key={item.filmId} {...item} ></FilmItem>
              })
            }
          </div>
          <Info></Info>
        </div>
      </GlobalContext.Provider>

    )
  }
}


class FilmItem extends Component {
  render () {
    let { name, synopsis, poster } = this.props
    return (
      <GlobalContext.Consumer>
        {
          (value) => {
            return (
              <div style={{ borderBottom: '1px solid black', width: '200px' }} onClick={() => {
                value.changeInfo(synopsis)
              }}>
                <h3>{name}</h3>
                <img src={poster} alt="" style={{ height: '50px', width: '50px' }} />
              </div>
            )
          }
        }
      </GlobalContext.Consumer>
    )
  }
}

class Info extends Component {
  render () {
    return (
      <GlobalContext.Consumer>
        {
          (value) => {
            return (
              <div style={{ position: 'fixed', top: '50px', right: '50px', width: '300px', height: '300px', background: 'yellow' }}>
                {value.info}
              </div>
            )
          }
        }
      </GlobalContext.Consumer>
    )
  }
}

插槽

在这里插入图片描述

import React, { Component } from 'react'

export default class App extends Component {
  render () {
    return (
      <div>
        我是父组件
        <Child>
          <div>我是插槽1</div>
          <div>我是插槽2</div>
        </Child>
      </div>
    )
  }
}


class Child extends Component {
  render () {
    return <div>
      {this.props.children}
      {this.props.children[1]}
    </div>
  }
}

生命周期

性能优化

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值