共计 7237 个字符,预计需要花费 19 分钟才能阅读完成。
前言:
最新在做 react 的 B 端我的项目、因为我的项目中没有用到 Redux 等数据管理库、所以波及到了很多组件之前的数据传递和嵌套组件如何传递的形式,温故而知新 特此整顿记录一下。
常见的组建通信的形式:
父子组件通信
子父组件通信
兄弟组件通信
爷孙通信(嵌套组件)
等等
代码环境:
react: ^16.13.0
react-dom:^16.8.2
父子组件通信:
通常来说是父组件通过 props、refs 等形式来调用子组件的办法和属性等;
props
: 子组件承受父组件的值进行视图更新
class 组件:
import React, {Component} from 'react'
// 子组件
class Child extends Component {constructor(props) {super(props)
this.state = {}}
render() {const { mun} = this.props;
return (
<>
这里是 child 子组件:<p>{mun}</p>
</>
)
}
}
// 父组件
class Parent extends Component {constructor(props) {super(props)
this.state = {mun:1}
}
handleParent = () => {
this.setState({mun: this.state.mun + 1})
}
render() {const { mun} = this.state
return (
<>
<button onClick={this.handleParent}> 我是父组件的按钮。你能够点击我 </button>
<br />
<Child mun={mun} />
</>
)
}
}
export default Parent
Hooks 组件:
import React, {useState} from 'react'
const Child = (props) => {const { mun} = props;
return (
<>
这里是 child 子组件:<p>{mun}</p>
</>
)
}
const Parent = () =>{const [mun, setMun] = useState(0)
const handleParent = () => {setMun((value) => {return value + 1})
}
return (
<>
<button onClick={handleParent}> 我是父组件的按钮。你能够点击我 </button>
<br />
<Child mun={mun} />
</>
)
}
export default Parent
refs
:父组件通过申明 ref 拿到子组件的对象、进行操作子组件的对象办法
class 组件:
import React, {Component, createRef} from 'react'
// 子组件
class Child extends Component {constructor(props) {super(props)
this.state = {mun:1}
}
// 子组件累加累加
accumulation = () => {
this.setState({mun: this.state.mun + 1})
}
render() {const { mun} = this.state
return (
<>
这里是 child 子组件:<p>{mun}</p>
</>
)
}
}
// 父组件
class Parent extends Component {constructor(props) {super(props)
// 通过 ref 管制
this.createRef = createRef()
this.state = {}}
handleParent = () => {this.createRef && this.createRef.current.accumulation()
}
render() {
return (
<>
<button onClick={this.handleParent}> 我是父组件的按钮。你能够点击我 </button>
<br />
<Child ref={this.createRef} />
</>
)
}
}
export default Parent
Hooks 组件:
留神
:在 hooks 中须要通过forwardRef
转发获取 ref
的值,而后通过 useImperativeHandle 向父组件抛出子组件的办法。
import React, {useRef, useState, useImperativeHandle, forwardRef} from 'react'
const Child = forwardRef((_, ref) => {const [mun, setMun] = useState(0)
// 累加办法
const accumulation = () => {setMun((value) => {return value + 1})
}
// 给父组件抛出办法
useImperativeHandle(ref, () => ({accumulation,}), [accumulation]);
return (
<>
这里是 child 子组件:<p>{mun}</p>
</>
)
})
const Parent = () =>{const ChildRef = useRef(null);
const handleParent = () => {ChildRef.current && ChildRef.current.accumulation()
}
return (
<>
<button onClick={handleParent}> 我是父组件的按钮。你能够点击我 </button>
<br />
<Child ref={ChildRef} />
</>
)
}
export default Parent
子父组件通信:
子组件通过 CallBack 回调函数的形式来拿到父组件的办法或者属性等
Class 组件:
import React, {Component, createRef} from 'react'
// 子组件
class Child extends Component {constructor(props) {super(props)
this.state = {mun:0}
}
// 子组件累加累加
accumulation = () => {const { handleParent} = this.props
const {mun} = this.state
this.setState({mun:this.state.mun + 1},() => {handleParent(this.state.mun)
})
}
render() {const { mun} = this.props
return (
<>
这里是 child 子组件:{/* <p>{ mun}</p> */}
<button onClick={this.accumulation}> 我是子组件的按钮、能够点击我 </button>
</>
)
}
}
// 父组件
class Parent extends Component {constructor(props) {super(props)
// 通过 ref 管制
this.ChildRef = createRef()
this.state = {getChildmun:0}
}
handleParent = (_mun) => {
this.setState({getChildmun:_mun})
}
render() {const { getChildmun} = this.state
return (
<>
<h2> 我是父组件 </h2>
<p> 子组件管制的值:{getChildmun}</p>
<br />
<Child handleParent={this.handleParent} />
</>
)
}
}
export default Parent
Hooks 组件:
import React, {useState, useEffect} from 'react'
const Child = (props) => {const { handleParent} = props;
const [mun,setMun] = useState(0)
// 子组件累加累加
const accumulation = () => {setMun((value) => {return value + 1})
}
useEffect(() => {if(mun !== 0) {handleParent(mun)
}
}, [mun]);
return (
<>
这里是 child 子组件:<button onClick={accumulation}> 我是子组件的按钮、能够点击我 </button>
</>
)
}
const Parent = () =>{const [getChildmun,setChildmun] = useState(0);
return (
<>
<h2> 我是父组件 </h2>
<p> 子组件管制的值:{getChildmun}</p>
<br />
<Child handleParent={(mun) => setChildmun(mun)} />
</>
)
}
export default Parent
兄弟组件通信:
兄弟组件通信个别都是在一个父组件下平级的两个兄弟组件、利用父组件当中介进行传递
Class 组件:
import React, {Component, createRef} from 'react'
// 子组件 1
class Child1 extends Component {constructor(props) {super(props)
this.state = {mun:0}
}
render() {const { brother} = this.props
return (
<>
<h2> 我是 Child1 组件:{brother}</h2>
</>
)
}
}
// 子组件 1
class Child2 extends Component {constructor(props) {super(props)
this.state = {mun:0}
}
// 扭转本人的值、通过父组件传递
accumulation = () => {const { brotherCallback} = this.props
this.setState({mun:this.state.mun + 1}, () => {brotherCallback(this.state.mun)
})
}
render() {const { mun} = this.props
return (
<>
<h2> 我是 Child2 组件:</h2>
<button onClick={this.accumulation}> 点击我 扭转 [Child1] 组件的值 </button>
</>
)
}
}
// 父组件
class Parent extends Component {constructor(props) {super(props)
// 通过 ref 管制
this.ChildRef = createRef()
this.state = {brother:0}
}
// 利用中介的形式
brotherCallback = (mun) => {
this.setState({brother:mun})
}
render() {const { brother} = this.state
return (
<>
<h2> 我是父组件 </h2>
<hr />
<Child1 brother={brother} />
<hr />
<Child2 brotherCallback={this.brotherCallback}/>
</>
)
}
}
export default Parent
Hooks 组件:
import React, {useState,useEffect} from 'react'
const Child1 = (props) => {const { brother} = props;
return (
<>
<h2> 我是 Child1 组件:{brother}</h2>
</>
)
}
const Child2 = (props) => {const [mun, setMun] = useState(0)
const {brotherCallback} = props
// 扭转本人的值、通过父组件传递
const accumulation = () => {setMun((value) => {return value + 1})
}
useEffect(() => {if(mun !== 0) {brotherCallback(mun)
}
}, [mun])
return (
<>
<h2> 我是 Child2 组件:</h2>
<button onClick={accumulation}> 点击我 扭转 [Child1] 组件的值 </button>
</>
)
}
const Parent = () => {const [brother,setBrother] = useState(0);
return (
<>
<h2> 我是父组件 </h2>
<hr />
<Child1 brother={brother} />
<hr />
<Child2 brotherCallback={(mun) => setBrother(mun)}/>
</>
)
}
export default Parent
(爷孙组件)嵌套组件:
嵌套组件其实也能够采纳父子组件的传递形式、然而如果层级过深显然不好保护,所以这里举荐采纳
Context
进行保护数据源的状态
详情请看:Context 文档形容的很具体。
Class 组件:
import React, {Component, createRef} from 'react'
// 前期能够把他独自放在一个 js 文件维护
const ThemeContext = React.createContext();
// 孙子组件
class Grandson extends Component{constructor(props) {super(props)
this.state = {}}
static contextType = ThemeContext;
shouting = () => {const { grandsonCallback} = this.context
grandsonCallback({massge:"我累了、覆灭吧"})
}
render() {const { parentObj} = this.context
return (
<>
<h2> 我是孙子组件 </h2>
<p> 接管的值:{parentObj.name} 年龄 {parentObj.age} 岁 </p>
<button onClick={this.shouting}> 隔空喊话 </button>
</>
)
}
}
// 儿子组件
class Child extends Component {constructor(props) {super(props)
this.state = {}}
render() {
return (
<>
<h2> 我是儿子组件 </h2>
<hr />
<Grandson />
</>
)
}
}
// 父组件
class Parent extends Component {constructor(props) {super(props)
this.state = {
parentObj:{
name:"我是你爷爷",
age:88
},
// 承受孙子组件的数据
grandson:{}}
}
grandsonCallback = (data) => {
this.setState({grandson:data})
}
render() {const { parentObj, grandson} = this.state;
return (
<>
<h2> 我是父组件 </h2>
<p>{(grandson && grandson.massge) ? grandson.massge : '' }</p>
<hr />
<ThemeContext.Provider value={{ parentObj, grandsonCallback: this.grandsonCallback} }>
<Child />
</ThemeContext.Provider>
</>
)
}
}
export default Parent
Hooks 组件:
import React, {useState, useContext} from 'react'
// 前期能够把他独自放在一个 js 文件维护
const ThemeContext = React.createContext();
const Grandson = () => {const context = useContext(ThemeContext)
const {parentObj, grandsonCallback} = context;
const shouting = () => {
grandsonCallback({massge:"我累了、覆灭吧"})
}
return (
<>
<h2> 我是孙子组件 </h2>
<p> 接管的值:{parentObj.name} 年龄 {parentObj.age} 岁 </p>
<button onClick={shouting}> 隔空喊话 </button>
</>
)
}
const Child = () => {
return (
<>
<h2> 我是儿子组件 </h2>
<hr />
<Grandson />
</>
)
}
const Parent = () =>{const [grandson, setGrandson] = useState({});
const [parentObj, setParentObj] = useState(
{
name:"我是你爷爷",
age:88
});
const grandsonCallback = (data) => {setGrandson(data)
}
return (
<>
<h2> 我是父组件 </h2>
<p>{(grandson && grandson.massge) ? grandson.massge : '' }</p>
<hr />
<ThemeContext.Provider value={{ parentObj, grandsonCallback} }>
<Child />
</ThemeContext.Provider>
</>
)
}
export default Parent
最初
其实在常见的组件通信中,以上的形式入不敷出、然而面对简单的大型项目中还是举荐采纳 redux 这样的状态存储对象来对立治理、如果 redux 灵活性不高,这里也举荐采纳 dva 进行治理、就像它的个性一样:疾速上手、易学易用。
正文完
发表至: javascript
2021-07-07