父子组件通讯
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>
}
}