react2 - 组件通信
-
父传子
父传子: 1. 在父组件使用子组件的地方,定义属性传参 2. 子组件中通过props接收参数,类组件需要this.props.属性名,函数组件.props.属性名 传参类型: 1. 字符串... 基本数据类型 2. 对象 {} 3. 函数 ()=>{} 4. jsx
export default class Parent1 extends Component { state = { message: '这是Parent1父组件内容', user: { name: 'jack', age: 18, }, } render() { return ( <div className="container"> <h2>父传子 Parent1组件</h2> <Son msg={this.state.message} user={this.state.user} callback={this.getMessage} jsxdemo={ <div> <p>jsx作为参数{this.state.message}</p> <p>价格:188.98</p> </div> } /> <SonF msg={this.state.message} user={this.state.user} jsxdemo={<h2>这是jsx传参,类似vue中插槽</h2>} /> </div> ) } getMessage = () => { console.log('这是传的函数参数') } }
// 类子组件 export default class Son extends Component { render() { return ( <div className="son-a"> <h2>Son组件</h2> <p>{this.props.msg}</p> <p>{this.props.user.name}</p> { this.props.jsxdemo } <button onClick={this.bindGetMessage}>确定</button> </div> ) } bindGetMessage = () => { let messg = this.props.callback messg() } } // 函数子组件 export default function SonF(props) { return ( <div className='son-f'> <h2>函数组件SonF</h2> <p>{props.msg}</p> <p>{props.user.age}</p> {/* 插槽位置 */} { props.jsxdemo } </div> ) }
-
子传父
export default class Parent extends Component { state={ content:'' } render() { return ( <div style={ {width:'400px',height:'400px',backgroundColor:'pink'} }> <h2>子传父 - 父组件Parent</h2> {/* 2. 带参的函数传给子组件 */} <Son2 emitMsg={ (msg)=>{this.getMessage(msg)} } /> {this.state.content} </div> ) } /** * 1. 定义一个带参的函数 * @param {*} msg 接收子组件实参 */ getMessage = (msg)=>{ console.log('msg ',msg); this.setState({content:msg}) } }
export default class Son2 extends Component { state = { content: '这是子组件内容', } render() { return ( <div style={ {width:'200px',height:'100px',backgroundColor:'skyblue'}}> <h2>Son2子组件</h2> <button onClick={this.bindSendMessage}>子传父</button> </div> ) } /** * 3. 点击按钮发送数据给父组件 */ bindSendMessage = () => { this.props.emitMsg(this.state.content) //在子组件中 调用父组件传递的函数参数 } }
-
兄弟组件通信
兄弟组件之间传递数据,可以将Son组件的数据传递给自己的父组件,父组件将数据传递给Son2组件。备注:父组件是 son 和 son2 的父亲。
/** * 兄弟组件通讯 * SonA组件内容发送给SonB组件显示 */ export default class SonA extends Component { state = { content:'这是SonA组件发送给SonB组件的内容' } render() { return ( <div style={ {width:'200px',height:'200px',backgroundColor:'skyblue'}}> <h2>SonA子组件</h2> <button onClick={()=>{ this.props.emitMsg(this.state.content) } }>发送信息</button> </div> ) } }
export default function SonB(props) { return ( <div style={ {width:'200px',height:'100px',backgroundColor:'pink'}}> <h2>SonB 组件</h2> <p>{props.sendMsg}</p> </div> ) } // 解构参数 // export default function SonB({sendMsg}) { // return ( // <div style={ {width:'200px',height:'100px',backgroundColor:'pink'}}> // <h2>SonB 组件</h2> // <p>{sendMsg}</p> // </div> // ) // }
-
提供者与消费者
- React.createContext
- Provider
- Consumer
- 提供者与消费者可以用来实现组件的跨级通信,提供者
provider
提供数据,消费者consumer
使用数据。需要注意的是provider
有一个固定的属性value
,consumer
需要使用函数然后返回jsx
的形式,这样设计便于传参。
// contextbus 对比于vue中的事件总线bus import React from "react" export const {Provider,Consumer} = React.createContext()
// 提供者 Provider 提供数据的组件 import { Provider } from './demo3/contextbus' export default class App extends Component { state = { message: '兄弟组件通讯-初始值', msg: '跨组件通讯-app组件内容', } render() { return ( <Provider value={this.state.msg}> <div className="container"> <h1>App 父组件</h1> {/* 父传子示例 <Parent1 />*/} {/* 子传父示例 <Parent /> {/* 兄弟通讯示例 */} {/* <SonA emitMsg={ (msg)=>{this.getMessage(msg)} }/> */} {/* <SonB sendMsg={this.state.message}/> */} {/* 跨组件通讯示例 */} {/* <ComA /> */} <RefDemo/> </div> </Provider> ) } /** * 带参的函数 * @param {*} msg */ getMessage = msg => { this.setState({ message: msg }) } }
// 消费者 Consumer 获得、使用数据的组件 可多个 export default class ComB extends Component { render() { return ( <div style={ {width:'100px',height:'100px',backgroundColor:'blue'}}> <h2>ComB</h2> <ComC/> <Consumer> { value => <h2>{value}</h2>} </Consumer> </div> ) } }
-
refs
-
Refs提供了一种方式,允许我们访问DOM节点或在render方法中创建React元素
-
使用React.createRef()创建的,并通过ref属性附加到React元素
-
ref属性:
-
当ref属性用于html元素时,构造函数中使用React.createRef()创建的ref接收底层DOM元素作为其current属性
-
当ref属性用于自定义class组件时,ref对象接收组件的挂载实例作为其current属性
语法: 1、使用React.createRef()创建的ref 例:this.bindNum = React.createRef() 2、在需传参的组件中使用ref属性 例: <Text2 ref={this.bindNum}/> 3、使用current属性获取DOM节点或组件 例:this.bindNum.current
-
export default class RefDemo extends Component { constructor() { super() this.pRef = React.createRef() this.counterRef = React.createRef() } state = { content:'' } render() { return ( <div> <h2>refs操作dom(react元素或子组件)</h2> <h2>{this.state.content}</h2> <p id="p1" ref={this.pRef}>操作React元素</p> <Counter ref={this.counterRef}/> <button onClick={this.bindUpdateContent}>更新内容</button> </div> ) } bindUpdateContent = () => { //原生js操作元素内容 // const pEle = document.getElementById('p1') // pEle.innerHTML = '新的内容' // const pEle = this.pRef.current // console.log(pEle); // pEle.innerHTML = '通过ref更改新的内容' const CounterEle = this.counterRef.current console.log('CounterEle ',CounterEle); console.log('CounterEle.state.num ',CounterEle.state.num); this.setState({content:CounterEle.state.num}) } }
export default class Counter extends Component { state = { num: 10, } render() { return ( <div style={ {width:'200px',height:'200px',backgroundColor:'skyblue'}}> <h2>Counter组件</h2> <p>{this.state.num}</p> </div> ) } }
-