笔记--React 组件进阶

1. 组件通讯介绍

在这里插入图片描述

2. 组件的 props

在这里插入图片描述

// 导入react
import React from "react";

// 创建组件
// 函数组件接受组件的数据
// function Hello(props){
//     console.log(props.name);
// }

// 类组件接收组件的数据
class Hello extends React.Component{
    constructor(props){
        super(props)
        // 必须要传props给super() 不然constructor里面拿不到props数据
        console.log(props);
    }
    render(){
        return (
            // props 是一个对象
            <p>{this.props.name}</p>
        )
    }
}

// 将组件暴露出去
export default Hello

在这里插入图片描述

3. 组件通讯的三种方式

3.1 父组件传递数据给子组件

在这里插入图片描述

3.2 子组件传递给父组件

在这里插入图片描述在这里插入图片描述

3.3 兄弟组件

在这里插入图片描述

// 导入react
import React from "react";

// 创建父组件
class Counter extends React.Component{
    state = {
        // 提供状态
        publicData:0
    }
    // 提供修改状态的方法
    sendData=()=>{
        this.setState({
            publicData:this.state.publicData+1
        })
    }
    render(){
        return (
            <div>
                <Child1 data = {this.state.publicData}></Child1>
                <Child2 sendData={this.sendData}></Child2>
            </div>
        )
    }
}

// 创建子组件
const Child1 = (props)=>{
    return (
        <p>计数:{props.data}</p>
    )
}
const Child2 = (props)=>{
    return (
        <button onClick={()=>props.sendData()}>点击+1</button>
    )
}

// 将父组件暴露出去
export default Counter

4. Context

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

// 导入react
import React from "react";

// 创建 Provider(提供数据) 和 Consumer(消费数据) 两个组件
const { Provider, Consumer } = React.createContext();

// 创建组件
class App extends React.Component{

    render(){
        return (
            <Provider value={'我是傻逼'}>
                <div>
                    <Node />
                </div>
            </Provider>
        )
    }
}

const Node =props => {
    return (
        <SubNode />
    )
}

const SubNode = props => {
    return (
        <Child />
    )
}

const Child = props => {
    return (
        <div>我是子节点
            <Consumer>
                {data=><h1>接收到的数据--{data}</h1>}
            </Consumer>
        </div>
    )
}

// 将App暴露出去
export default App

在这里插入图片描述

5. props 深入

5.1 children 属性

在这里插入图片描述

// 导入react
import React from "react";

// 创建组件
class Hello extends React.Component{

    render(){
        return (
            <div>
                组件的子节点:{this.props.children}
                {console.log(this.props.children)}
            </div>
        )
    }
}

// 将组件暴露出去
export default Hello

// index文件渲染
// ReactDOM.render(<Change><h1>我是一个大傻逼</h1></Change>, document.querySelector('#root'))

5.2 props 校验

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

// 1. 导入react,react-dom 两个包
import React from 'react'
import ReactDOM from 'react-dom'
// 导入prop-types包
import PropTypes from 'prop-types'

// 导入css
import './index.css'

// 添加组件
function App(props){
    return (
        <div>{props.a}{props.fn()}{props.tag}{props.fiter.area}</div>
    )
}

// 约定属性类型
// 添加props校验
// 属性 a 的类型: 数值(number)
// 属性 fn 的类型: 函数(func) 并且为必填项
// 属性 tag 的类型: React元素(element)
// 属性 fiter 的类型: 对象(area:'上海', price: 1999)
App.propTypes = {
    // 约定color属性为Arry
    // 如果类型不对,则报出明确错误,便于分析错误原因
    a: PropTypes.number,
    fn: PropTypes.func.isRequired,
    tag: PropTypes.element,
    fiter: PropTypes.shape({
        area: PropTypes.string,
        price: PropTypes.number
    })
}

// 渲染
ReactDOM.render(<App fn={()=><p>666</p>} a={11} tag={<h1>我是一个大傻逼</h1>} fiter={{area:'sdad',price:131232}}></App>, document.querySelector('#root'))

5.3 props 的默认值

在这里插入图片描述

6. 组件的生命周期

6.1 组件的生命周期概述

在这里插入图片描述

6.2 生命周期的三个阶段

在这里插入图片描述

1. 创建时( 挂载阶段 )

在这里插入图片描述

// 1. 导入react,react-dom 两个包
import React from 'react'
import ReactDOM from 'react-dom'
// 导入prop-types包
import PropTypes from 'prop-types'

// 导入css
import './index.css'

// 添加组件
class App extends React.Component{
    constructor(){
        super()
        console.warn('挂载时:constructor');
    }

    // 1. 进行DOM操作
    // 2. 发送ajax请求, 获取远程数据
    componentDidMount(){
        // axios.get('http://api.....')
        const title = document.querySelector('#title');
        console.log(title);
        console.warn('挂载时:componentDidMount');
    }

    render(){
        console.warn('挂载时:render');
        return (
            <div>
                <h1 id="title">生命周期</h1>
            </div>
        )
    }
}

// 添加props默认值
App.defaultProps={
    pageSize:10
}

// 渲染
ReactDOM.render(<App></App>, document.querySelector('#root'))

2. 更新时(更新阶段)

在这里插入图片描述

// 1. 导入react,react-dom 两个包
import React from 'react'
import ReactDOM from 'react-dom'
// 导入prop-types包
import PropTypes from 'prop-types'

// 导入css
import './index.css'

// 添加组件
class App extends React.Component{
    constructor(){
        super()

    }
    state ={
        count:0
    }

    // 状态加1
    countAdd= ()=>{
        this.setState({
            count:this.state.count+1
        })

        // 演示强制更新
        // this.forceUpdate() 
    }
    render(){
        console.warn('render');
        return (
            <div>
                <Count count={this.state.count}></Count>
                <button onClick={this.countAdd}>点击</button>
            </div>
        )
    }   
}

// 子组件
class Count extends React.Component{

    render(){
        console.warn('count-render');
        return (
            <h1 id='count'>计数:{this.props.count}</h1>
        )
    }

    // 注意:如果要调用 setState() 更新状态,必须放在一个 if 条件中
    // 因为:如果直接调用 setState() 更新状态,也会导致递归更新!!!
    componentDidUpdate(prevProps){
        const h = document.getElementById('count')
        console.log(h);

        // 错误演示!!!
        // this.setState({})
        // 正确做法:
        // 做法: 比较更新前后的props是否相同,来决定是否重新渲染组件
        console.log('上一次的prevProps:',prevProps,'当前的prevProps:',this.props);
        if(prevProps.count!==this.props.count){
            this.setState({
            })
        }
    }
}
// 渲染
ReactDOM.render(<App></App>, document.querySelector('#root'))

3. 卸载时(卸载阶段)

在这里插入图片描述

// 1. 导入react,react-dom 两个包
import React from 'react'
import ReactDOM from 'react-dom'
// 导入prop-types包
import PropTypes, { func } from 'prop-types'

// 导入css
import './index.css'

// 添加组件
class App extends React.Component{
    constructor(){
        super()

    }
    state ={
        count:0
    }

    // 状态加1
    countAdd= ()=>{
        this.setState({
            count:this.state.count+1
        })

        // 演示强制更新
        // this.forceUpdate() 
    }
    render(){
        console.warn('render');
        return (
            <div>
                {
                    this.state.count > 4
                    ? (<h1>豆豆被打死了</h1>)
                    : (<Count count={this.state.count}></Count>)
                } 
                <button onClick={this.countAdd}>点击</button>
            </div>
        )
    }   
}

// 子组件
class Count extends React.Component{

    componentDidMount(){
        // 开启定时器
        this.timerId=setInterval(()=>{
            console.log(111);
        },1000)
    }
    render(){
        console.warn('count-render');
        return (
            <h1 id='count'>计数:{this.props.count}</h1>
        )
    }
    componentWillUnmount() {
        console.log('生命周期钩子函数: componentWillUnmount');
        // 清除定时器
        clearInterval(this.timerId)
    }
}
// 渲染
ReactDOM.render(<App></App>, document.querySelector('#root'))

6.3 不常用钩子函数介绍

在这里插入图片描述
在这里插入图片描述

7. render-props 和高阶组件

7.1 React 组件复用概述

在这里插入图片描述

7.2 render props 模式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

// 导入react reactDOM包
import React from "react";
import ReactDOM from "react-dom";

// render proprs模式

// 导入图片
import img from "./image/submarine.webp";

// 创建Mouse组件
class Mouse extends React.Component {
  state = {
    // 鼠标位置
    x: 0,
    y: 0,
  };

  // 鼠标移动事件的处理程序
  mouseListen = (e) => {
    this.setState({
      x: e.clientX,
      y: e.clientY,
    });
  };

  componentDidMount() {
    // 监听鼠标的移动
    window.addEventListener("mousemove", this.mouseListen);
  }

  render() {
    // return null
    return this.props.render(this.state);
  }
}

class App extends React.Component {
  render() {
    return (
      <div>
        <h1>render props 模式 </h1>
        <Mouse
          render={(mouse) => {
            return (
              <h1>
                X:{mouse.x},Y:{mouse.y}
              </h1>
            );
          }}
        />

        {/* 猫捉老鼠 */}
        <Mouse
          render={(mouse) => {
            return (
              <img
                src={img}
                alt="小飞机"
                style={{
                  position: "absolute",
                  width: 50,
                  height: 50,
                  left: mouse.x,
                  top: mouse.y,
                }}
              />
            );
          }}
        />
      </div>
    );
  }
}

// 渲染
ReactDOM.render(<App />, document.getElementById("root"));

在这里插入图片描述

在这里插入图片描述

// 导入react reactDOM包
import React from "react";
import ReactDOM from "react-dom";

// 导入属性校验的包
import PropTypes from "prop-types";

// render proprs模式

// 导入图片
import img from "./image/submarine.webp";

// 创建Mouse组件
class Mouse extends React.Component {
  state = {
    // 鼠标位置
    x: 0,
    y: 0,
  };

  // 鼠标移动事件的处理程序
  mouseListen = (e) => {
    this.setState({
      x: e.clientX,
      y: e.clientY,
    });
  };

  componentDidMount() {
    // 监听鼠标的移动
    window.addEventListener("mousemove", this.mouseListen);
  }

  // 推荐在组件卸载时,移除事件绑定
  componentWillUnmount() {
    window.removeEventListener("mousemove", this.mouseListen);
    console.log(33);
  }
  render() {
    // return null
    return this.props.children(this.state);
  }
}

// 属性校验
Mouse.propTypes = {
  children: PropTypes.func.isRequired,
};

class App extends React.Component {
  render() {
    return (
      <div>
        <h1>render props 模式 </h1>
        <Mouse>
          {(mouse) => {
            return (
              <h1>
                X:{mouse.x},Y:{mouse.y}
              </h1>
            );
          }}
        </Mouse>

        {/* 猫捉老鼠 */}
        <Mouse>
          {(mouse) => {
            return (
              <img
                src={img}
                alt="小飞机"
                style={{
                  position: "absolute",
                  width: 50,
                  height: 50,
                  left: mouse.x,
                  top: mouse.y,
                }}
              />
            );
          }}
        </Mouse>
      </div>
    );
  }
}

// 渲染
ReactDOM.render(<App />, document.getElementById("root"));

7.3 高阶组件

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

设置displayName

在这里插入图片描述

// 导入react reactDOM包
import React from "react";
import ReactDOM from "react-dom";

// 导入属性校验的包
import PropTypes, { func } from "prop-types";

// 高阶组件 HOC

// 导入图片
import img from "./image/submarine.webp";

// 创建高阶组件
function withMouse(WrappedComponent) {
  // 创建Mouse组件
  class Mouse extends React.Component {
    // 设置鼠标状态值
    state = {
      x: 0,
      y: 0,
    };

    // 控制鼠标逻辑
    componentDidMount() {
      // 绑定事件
      window.addEventListener("mousemove", this.mouseMove);
    }

    componentWillUnmount() {
      // 清除事件
      window.removeEventListener("mousemove", this.mouseMove);
    }
    // 鼠标事件
    mouseMove = (e) => {
      this.setState({
        x: e.clientX,
        y: e.clientY,
      });
    };

    render() {
      return <WrappedComponent {...this.state} {...this.props}></WrappedComponent>;
    }
  }

  // 设置displayName
  Mouse.displayName = `WithMouse${getDispalyName(WrappedComponent)}`;

  // 将组件返回出去
  return Mouse;
}

// 设置组件displayName 方法
function getDispalyName(WrappedComponent) {
  return WrappedComponent.displayName || WrappedComponent.name || "Component";
}
// 用来测试的组件
const Position = (props) => {
  return (
    <h1>
      X:{props.x},Y:{props.y}
    </h1>
  );
};
// 用来测试的组件二:猫捉老鼠
const MoveImg = (props) => {
  return (
    <img
      src={img}
      alt="小飞机"
      style={{
        position: "absolute",
        width: 50,
        height: 50,
        left: props.x,
        top: props.y,
      }}
    />
  );
};
// 获取增强后的组件
const MousePosition = withMouse(Position);
const MouseMoveImg = withMouse(MoveImg);

class App extends React.Component {
  render() {
    return (
      <div>
        <h1>render props 模式 </h1>
        <MousePosition />
        <MouseMoveImg />
      </div>
    );
  }
}

// 渲染
ReactDOM.render(<App />, document.getElementById("root"));

传递 props

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值