React-2 组件通信

react2 - 组件通信

  1. 父传子

    父传子:
        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>
      )
    }
    
    
  2. 子传父

    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) //在子组件中 调用父组件传递的函数参数
        }
    }
    
    
  3. 兄弟组件通信

    兄弟组件之间传递数据,可以将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>
    //     )
    //   }
      
    
  4. 提供者与消费者

    • React.createContext
    • Provider
    • Consumer
    • 提供者与消费者可以用来实现组件的跨级通信,提供者 provider 提供数据,消费者 consumer 使用数据。需要注意的是 provider 有一个固定的属性 valueconsumer 需要使用函数然后返回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>
        )
      }
    }
    
  5. 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>
    		)
    	}
    }
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值