React学习二

组件通信

在函数组件中通过接收props参数可以直接获取传入的状态
在类组件中使用this.props获取
props可以传递任意状态、jsx语法、函数等等

import React from "react";
import ReactDOM from 'react-dom'

// const Hello = props => {
//     return (
//         <div>
//             <h1>props: {props.name}</h1>
//         </div>
//     )
// }

// class Hello extends React.Component {
//     render() {
//         return (
//             <div>
//                 <h1>props: { this.props.name }</h1>
//             </div>
//         )
//     }
// }

class Hello extends React.Component {
    constructor(props) {
        super(props);
        console.log(props)
    }
    render() {
        return (
            <div>
                <h1>props: { this.props.name }</h1>
            </div>
        )
    }
}
ReactDOM.render(<Hello name='jack' age={19}/>,document.getElementById('root'))

父传子

import React from "react";
import ReactDOM from 'react-dom'

class Parent extends React.Component {
    state = {
        lastName:'王'
    }

    render() {
        return (
            <div className='parent'>
                父组件
                <Child name={ this.state.lastName }/>
            </div>
        )
    }
}
const Child = (props) => {
    return (
        <div className='child'>
            <p>子组件,接收到父组件的数据:{ props.name }</p>
        </div>
    )
}
ReactDOM.render(<Parent/>,document.getElementById('root'))

子传父

子传父需要在父组件定义一个方法,再将这个方法传给子组件,子组件调用这个方法,同时把状态作为实参传入父组件的方法,父组件就可以拿到传入的状态了

import React from "react";
import ReactDOM from 'react-dom'

class Parent extends React.Component {
    getChildMsg = data => {
        alert(data)
    }
    render() {
        return (
            <div className='parent'>
                父组件
                <Child getMsg={ this.getChildMsg }/>
            </div>
        )
    }
}
class Child extends React.Component {
    state = {
        msg:'Battle cruise'
    }
    handleClick = () => {
        this.props.getMsg(this.state.msg)
    }
    render() {
        return (
            <div className='child'>
                子组件:<button onClick={this.handleClick}>点我,给父组件传递数据</button>
            </div>
        )
    }
}

ReactDOM.render(<Parent/>,document.getElementById('root'))

兄弟通信

兄弟通信是使用的状态提升方法,通过共同的父组件作为中间交换状态。

import React from "react";
import ReactDOM from 'react-dom'

class Counter extends React.Component {
    state = {
        count:0
    }
    onIncrement = () => {
        this.setState({
            count:this.state.count + 1
        })
    }
    render() {
        return (
            <div>
                <Child1 count={this.state.count}/>
                <Child2 onIncrement={this.onIncrement}/>
            </div>
        )
    }
}

const Child1 = (props) => {
    return <h1>计数器:{props.count}</h1>
}
const Child2 = (props) => {
    return <button onClick={()=>props.onIncrement()}>+1</button>
}

ReactDOM.render(<Counter/>,document.getElementById('root'))

Context通信

本质上是使用的props的children方法实现的,通过React.createContext()方法获取Provider 和 Consumer 。给传出数据的组件渲染函数外套上并传入value数据。
在传入数据的组件渲染函数里使用,在内部使用函数形参接受传入的数据并使用

import React from "react";
import ReactDOM from 'react-dom'

const { Provider ,Consumer } = React.createContext()

class App extends React.Component {
    render() {
        return (
            <Provider value='pink'>
                <div className='app'>
                    <Node/>
                </div>
            </Provider>
        )
    }
}
const Node = prop => {
    return (
        <div className='node'>
            <SubNode/>
        </div>
    )
}
const SubNode = props => {
    return (
        <div className='subnode'>
            <Child/>
        </div>
    )
}
const Child = props => {
    return (
        <div className='child'>
            <Consumer>
                {
                    data => <span>我是子节点 -- { data }</span>
                }
            </Consumer>
            我是子节点
        </div>
    )
}
ReactDOM.render(<App/>,document.getElementById('root'))

props中children

render函数中组件双标签中传入内容,组件可以使用props.children或者this.props.children获取传入的内容

import React from "react";
import ReactDOM from 'react-dom'

// const App = props => {
//     console.log(props)
//     return (
//         <div>
//             <h1>组件标签的子节点:</h1>
//             {props.children}
//         </div>
//     )
// }
//
// ReactDOM.render(<App>我是子节点</App>,document.getElementById('root'))

const Test = () => <button>我是button组件</button>
const App = props => {
    console.log(props)
    return (
        <div>
            <h1>组件标签的子节点:</h1>
            {props.children}
        </div>
    )
}

ReactDOM.render(
    <App>
        <Test/>
    </App>,
    document.getElementById('root'))
    

组件生命周期

创建时

import React from 'react'
import ReactDOM from 'react-dom'

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            count:0
        }
        console.log('生命周期钩子函数:constructor')
    }
    componentDidMount() {
        const title = document.getElementById('title')
        console.log(title)
        console.log('生命周期钩子函数:componentDidMount')
    }

    render() {
        console.log('生命周期钩子函数:render')
        return (
            <div>
                <h1 id='title'>统计豆豆被打的次数:</h1>
                <button id='btn'>打豆豆</button>
            </div>
        )
    }
}
ReactDOM.render(<App/>,document.getElementById('root'))

更新时

import React from 'react'
import ReactDOM from 'react-dom'

class App extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            count:0
        }
    }
    handleClick = () => {
        // this.setState({
        //     count:this.state.count + 1
        // })

        //  强制更新
        this.forceUpdate()
    }
    render() {
        console.log('生命周期钩子函数:render')
        return (
            <div>
                <Counter count={this.state.count}/>
                <button onClick={this.handleClick}>打豆豆</button>
            </div>
        )
    }
}
class Counter extends React.Component {
    render() {
        console.log('子组件生命周期钩子函数:render')
        return (
            <h1>统计豆豆被打的次数:{this.props.count}</h1>
        )
    }
}
ReactDOM.render(<App/>,document.getElementById('root'))

更新时注意:
如果在更新时的钩子函数componentDidUpdate()中调用setState()方法,必须在条件判断中,否则会导致递归更新,报错!!

import React from 'react'
import ReactDOM from 'react-dom'

class App extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            count:0
        }
    }

    handleClick = () => {
        this.setState({
            count:this.state.count + 1
        })

        //  强制更新
        // this.forceUpdate()
    }

    render() {
        return (`在这里插入代码片`
            <div>
                <Counter count={this.state.count}/>
                <button onClick={this.handleClick}>打豆豆</button>
            </div>
        )
    }
}

class Counter extends React.Component {
    render() {
        console.log('子组件-生命周期钩子函数:render')
        return (
            <h1 id='title'>统计豆豆被打的次数:{this.props.count}</h1>
        )
    }

    componentDidUpdate(prevProps, prevState, snapshot) {
        console.log('子组件-生命周期钩子函数:componentDidUpdate')

        //  如果要调用setState()更新状态,必须要放在判断条件中,否则会导致递归更新报错!!
        if (prevProps.count !== this.props.count){
            this.setState({})
        }
    }
}
ReactDOM.render(<App/>,document.getElementById('root'))

组件复用

render props模式组件复用

import React from "react";
import ReactDOM from 'react-dom'

import img from './images/cat.png'

class Mouse extends React.Component {
    state = {
        x:0,
        y:0
    }
    handleMouseMove = (e) => {
        this.setState({
            x:e.clientX,
            y:e.clientY
        })
    }
    componentDidMount() {
        window.addEventListener('mousemove',this.handleMouseMove)
    }
    render() {
        return this.props.render(this.state)
    }
}
class App extends React.Component {
    render() {
        return (
            <div>
                <h1>render props 模式</h1>
                <Mouse render={(mouse)=><p>鼠标当前位置:{mouse.x},{mouse.y}</p>}/>

                <Mouse render={(mouse)=>{
                    return <img src={ img } alt="cat" style={{
                        position:'absolute',
                        top:mouse.y - 64,
                        left:mouse.x - 64,

                    }}/>
                }}/>
            </div>
        );
    }
}
ReactDOM.render(<App/>,document.getElementById('root'))

使用children进行优化:

import React from "react";
import ReactDOM from 'react-dom'

import img from './images/cat.png'

class Mouse extends React.Component {
    state = {
        x:0,
        y:0
    }
    handleMouseMove = (e) => {
        this.setState({
            x:e.clientX,
            y:e.clientY
        })
    }
    componentDidMount() {
        window.addEventListener('mousemove',this.handleMouseMove)
    }
    //  组件卸载时 移除事件绑定
    componentWillUnmount() {
        window.removeEventListener('mousemove',this.handleMouseMove)
    }
    render() {
        return this.props.children(this.state)
    }
}
class App extends React.Component {
    render() {
        return (
            <div>
                <h1>render props 模式</h1>
                <Mouse>{
                    (mouse)=>{
                        return (
                            <p>鼠标当前位置:{mouse.x},{mouse.y}</p>
                        )
                    }
                }</Mouse>
                <Mouse>
                    {
                        (mouse)=>{
                            return <img src={ img } alt="cat" style={{
                                position:'absolute',
                                top:mouse.y - 64,
                                left:mouse.x - 64,
                            }}/>
                        }
                    }
                </Mouse>
            </div>
        );
    }
}
ReactDOM.render(<App/>,document.getElementById('root'))

高阶组件
高阶组件就是利用通用逻辑的组件在内部对可能存在的同时使用该逻辑的组件进行一次封装,再把它们返回出去,但是不负责渲染,而需要渲染时直接使用二次封装后的组件标签便可以实现对组件的共用。
b站这个视频讲解的不错,可以看看》》》》

import React from 'react'
import ReactDOM from 'react-dom'

import img from './images/cat.png'

//创建高阶组件
function withMouse(WrappedComponent) {
    class Mouse extends React.Component {
        state = {
            x: 0,
            y: 0
        }

        handleMouseMove = (e) => {
            this.setState({
                x: e.clientX,
                y: e.clientY
            })
        }
        componentDidMount() {
            window.addEventListener('mousemove', this.handleMouseMove)
        }

        componentWillUnmount() {
            window.removeEventListener('mousemove', this.handleMouseMove)
        }
        render() {
            return (
                <WrappedComponent {...this.state} {...this.props}/>
                // 这块对porps也进行展开是为了后续组件之间可能存在的通信
            );
        }

    }
    // 设置组件名字,方便devtools调试用
    Mouse.displayName = `withMouse${getDisplayName(WrappedComponent)}`
    return Mouse
}

function getDisplayName(WrappedComponent){
    return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}


const Position = props => (
    <p>
        鼠标当前位置:(x:{props.x},y:{props.y})
    </p>
)
const Cat = props => (
    <img src={img} alt="cat" style={{
        position: 'absolute',
        top: props.y - 64,
        left: props.x - 64
    }}/>
)

const MousePosition = withMouse(Position)
const CatPosition = withMouse(Cat)

class App extends React.Component {
    render() {
        return (
            <div>
                <h1>高阶组件</h1>
                <MousePosition/>
                <CatPosition/>
            </div>
        )
    }
}
ReactDOM.render(<App/>, document.getElementById('root'))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值