React 扩展

news2024/11/16 9:41:55

文章目录

  • PureComponent
    • 1. 使用 React.Component,不会进行浅比较
    • 2. 使用 shouldComponentUpdate 生命周期钩子,手动比较
    • 3. 使用 React.PureComponent,自动进行浅比较
  • Render Props
    • 1. 使用 Children props(通过组件标签体传入结构)
    • 2. 使用 Render Props(通过组件标签属性传入结构)
  • Error Boundaries(错误边界)

PureComponent

PureComponent 在其内部实现了 shouldComponentUpdate() 方法的浅比较逻辑。当组件的 props 或 state 发生变化时,React 会通过这个方法检查前后的 props 和 state 是否相等。

如果 shouldComponentUpdate() 返回 false,则 React 不会触发组件的重新渲染过程,这可以避免不必要的渲染和可能带来的性能开销。

1. 使用 React.Component,不会进行浅比较

当执行this.setState({})时:

  • <Parent />组件 中 state 没有发生变化,也会重新执行render()
  • <Child />组件 没有接收任何props,也会重新执行render()
    .

不管父子组件的 props 或 state 有没有发生变化,都会重新执行各自的render(),重新渲染组件。这显然不符合逻辑,效率低下

import React, { Component } from 'react'

export default class Parent extends Component {

    state = { name: '张三' }

    changeName = () => {
        this.setState({})
    }

    render () {
        console.log('Parent render');
        return (
            <div>
                <button onClick={this.changeName}>点击</button>
                <Child />
            </div>
        )
    }
}


class Child extends Component {
    render () {
        console.log('Child render');
        return (
            <div>
                Child
            </div>
        )
    }
}

.

2. 使用 shouldComponentUpdate 生命周期钩子,手动比较

使用 shouldComponentUpdate 生命周期钩子,手动判断 props 或 state 的发生变化:

  • 如果父组件数据没有更新,则父组件和子组件都不需要重新render():父组件 => shouldComponentUpdate () { return false }
  • 如果父组件数据有更新,则父组件需要重新render():父组件 => shouldComponentUpdate () { return true }
  • 子组件则判断props数据有没有更新:子组件 => shouldComponentUpdate (nextProps, nextState) { return !this.props.name === nextProps.name }
import React, { Component, PureComponent } from 'react'

export default class Parent extends Component {

    state = { name: '张三' }

    changeName = () => {
        this.setState({})
    }

    shouldComponentUpdate (nextProps, nextState) {
    	// 当执行 this.setState({})时,state中数据没有变化时, return false 阻止更新.这样就不会重新渲染Parent组件,Child组件也不会更新
    	// 当执行 this.setState({ name: '李四' })时,state中数据发生改变, return true 这会重新渲染Parent组件,这是Child组件的props会改变
        if (this.state.name === nextState.name) {
            return false
        } else {
            return true
        }
    }

    render () {
        console.log('Parent render');
        return (
            <div>
                <button onClick={this.changeName}>点击</button>
                <Child name={this.state.name} />
            </div>
        )
    }
}


class Child extends Component {
	
	// 如果接收到的props中数据没有变化,则return false,阻止组件更新
    shouldComponentUpdate (nextProps, nextState) {
        if (this.props.name === nextProps.name) {
            return false
        } else {
            return true
        }
    }

    render () {
        console.log('Child render');
        return (
            <div>
                Child
                {this.props.name}
            </div>
        )
    }
}

3. 使用 React.PureComponent,自动进行浅比较

PureComponent 在其内部实现了 shouldComponentUpdate() 方法的浅比较逻辑。当组件的 props 或 state 发生变化时,React 会通过这个方法检查前后的 props 和 state 是否相等。

import React, { PureComponent } from 'react'

export default class Parent extends PureComponent {

    state = { name: '张三' }

    changeName = () => {
        this.setState({})
    }

	// 相当于PureComponent中内置shouldComponentUpdate的判断逻辑
    // shouldComponentUpdate (nextProps, nextState) {
    //     return !this.state.name === nextState.name
    // }

    render () {
        console.log('Parent render');
        return (
            <div>
                <button onClick={this.changeName}>点击</button>
                <Child name={this.state.name} />
            </div>
        )
    }
}


class Child extends PureComponent {

	// 相当于PureComponent中内置shouldComponentUpdate的判断逻辑
    // shouldComponentUpdate (nextProps, nextState) {
    //     return !this.props.name === nextProps.name
    // }

    render () {
        console.log('Child render');
        return (
            <div>
                Child
                {this.props.name}
            </div>
        )
    }
}


Render Props

在React中,并没有直接对应于 Vue.js 中的 “插槽”(slot)的概念。Vue.js的插槽允许你在子组件的模板中预留一些占位符,这些占位符可以由父组件来填充内容。

然而,React通过其组合和props传递的特性,提供了类似的功能,但实现方式略有不同。

1. 使用 Children props(通过组件标签体传入结构)

在子组件中可以通过 this.props.children 接收并渲染父组件传递的任何内容

import React, { Component } from 'react'

export default class Parent extends Component {

    state = { name: '张三' }

    render () {
        return (
            <Child>
                <p>这是一段文本。</p>
                <button>这是一个按钮。</button>
            </Child>
        )
    }
}


class Child extends Component {
    render () {
        return (
            <div className='childNode'>
                {/* 获取到<Child>中的标签属性 */}
                {this.props.children} // 这里可以接收并渲染父组件传递的任何内容
            </div>
        )
    }
}

<Child> 内部的两个节点插入到 .childNode

在这里插入图片描述

多层嵌套

  • 通过 <Child> <Grand/> </Child> 的形式,形成父子组件

  • 通过{this.props.children}的形式,渲染内容

import React, { Component } from 'react'

// 父组件  
export default class Parent extends Component {

    state = { name: '张三' }

    render () {
        return (
            <Child>
            	{/* Grand是Child的子组件 */}
                <Grand name={this.state.name} />
            </Child>
        )
    }
}

// 子组件  
class Child extends Component {

	state = { name: '李四' }

    render () {
        return (
            <div className='childNode'>
                <p>Child组件</p>
                {this.props.children}
            </div>
        )
    }
}

// 孙子组件  
class Grand extends Component {
    render () {
        return (
            <div className='grandNode'>
                <p>Grand组件</p>
                <p>{this.props.name}</p>
            </div>
        )
    }
}

但这样 Child 组件里的数据(state = { name: '李四' })无法传递给 Grand 组件,因此需要使用 Render Props

.

2. 使用 Render Props(通过组件标签属性传入结构)

Render props是一种在React组件之间共享代码的模式。一个组件接收一个返回React元素的函数作为prop,并在其渲染方法中调用该函数。这使得父组件能够动态地决定子组件应该渲染什么内容。

  • 通过 <Child render={() => <Grand />} /> 的形式,形成父子组件:render prop 的模式来在 Child 组件中动态渲染 Grand 组件

  • 通过{this.props.render()}的形式,动态渲染内容

import React, { Component } from 'react'

// 父组件  
export default class Parent extends Component {

    state = { name: '张三' }

    render () {
        return (
        	// 通过 render prop 的模式来在 Child 组件中动态渲染 Grand 组件
            <Child render={(name) => <Grand name={name} />} />
        )
    }
}

// 子组件  
class Child extends Component {

    state = { name: '李四' }

    render () {
        return (
            <div className='childNode'>
                <p>Child组件</p>
                
				{/* <Grand>组件被放置在这里,并传入Child组件的数据(name: '李四') */}
				{/* 相当与vue中<slot>插槽,动态渲染的位置 */}
                {this.props.render(this.state.name)}  
            </div>
        )
    }
}

// 孙子组件  
class Grand extends Component {
    render () {
        return (
            <div className='grandNode'>
                <p>Grand组件</p>
                <p>{this.props.name}</p>
            </div>
        )
    }
}

这样 Child 组件里的数据(state = { name: '李四' })就可以传递给 Grand 组件
在这里插入图片描述



Error Boundaries(错误边界)

正常情况下,子组件在任何位置的报错,都会使整个页面崩溃。

import React, { Component } from 'react'

// 父组件  
export default class Parent extends Component {
    render () {
        return (
            <div>
                <h2>父组件Parent</h2>
                <Child />
            </div>
        )
    }
}

// 子组件  
class Child extends Component {

    state = {
        list: '', // 会导致 this.state.list.map 报错,从而使整个页面崩溃
        // list: [
        //     { id: 1, name: '张三' },
        //     { id: 2, name: '李四' },
        //     { id: 3, name: '王五' },
        // ]
    }

    render () {
        return (
            <ul>
                {this.state.list.map((item) => {
                    return <li key={item.id}>{item.name}</li>
                })}
            </ul>
        )
    }
}

上例中,state.list='' 会导致 this.state.list.map 报错,从而使整个页面被摧毁。

在这里插入图片描述

.

使用 Error Boundaries 可以把错误被限定在指定的边界,并捕获错误信息,来确保单个错误或异常不会导致整个应用程序或页面崩溃。

在 React 中,Error Boundaries 是一种特殊的组件,可以捕获并打印发生在其子组件树任何位置的 JavaScript 错误,并且,它会阻止整个 React 组件树被这个错误摧毁。当错误被捕获后,Error Boundary 可以选择显示一个降级 UI 而不是崩溃的组件树,这允许用户可以继续使用应用的其他部分。

要使用 Error Boundaries,需要创建一个类组件,并在其中实现 static getDerivedStateFromError()componentDidCatch() 这两个生命周期方法。

  • static getDerivedStateFromError() : 当子组件出现报错时,会触发该回调,并携带错误信息
  • componentDidCatch(): 渲染组件时出错会被调用,常用于统计错误信息并传给后台

注意:

  • 只有生产环境才生效
  • 只能捕获后代组件生命周期中抛出的错误,不能捕获自身组件产生的错误
  • 不是生命周期的错误无法捕获
import React, { Component } from 'react'

// 父组件  
export default class Parent extends Component {

    state = {
        hasError: ''// 用于标识子组件是否产生错误
    }

    // 当Parent的子组件出现报错时,会触发getDerivedStateFromError调用,并携带错误信息
    static getDerivedStateFromError (error) {
        console.log('getDerivedStateFromError:', error);
        return { hasError: error }  // 返回一个error状态,并更新state中的hasError
    }

    componentDidCatch (error, errorInfo) {
        console.log('渲染组件时出错会被调用');

       // 可以将错误日志上报给服务器 
       console.error("Caught an error in ErrorBoundary", error, errorInfo);

       // 还可以将错误信息存储在 state 中  
       // this.setState({  
       //   error: error,  
       //   errorInfo: errorInfo  
       // });
   }

    render () {
        return (
            <div>
                <h2>父组件Parent</h2>
                {this.state.hasError ? <h2>子组件出错</h2> : <Child />}
            </div>
        )
    }
}

// 子组件  
class Child extends Component {

    state = {
        list: '',
        // list: [
        //     { id: 1, name: '张三' },
        //     { id: 2, name: '李四' },
        //     { id: 3, name: '王五' },
        // ]
    }

    render () {
        return (
            <ul>
                {this.state.list.map((item) => {
                    return <li key={item.id}>{item.name}</li>
                })}
            </ul>
        )
    }
}

父组件正常显示,报错的子组件则显示 <h2>子组件出错</h2>

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1859485.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nginx负载均衡案例,缓存知识----补充

负载均衡案例 ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near great all on wordpress.* to wp172.16.1.% indentified by 1 at line 1 MariaDB [(none)]>…

iptables(5)常用扩展模块iprange、string、time、connlimit、limit

简介 之前我们已经介绍过扩展模块的简单使用,比如使用-m tcp/udp ,-m multiport参数通过--dports,--sports可以设置连续和非连续的端口范围。那么我们如何匹配其他的一些参数呢,比如源地址范围,目的地址范围,时间范围等,这就是我们这篇文章介绍的内容。 iprange扩展模块…

Jmeter插件管理器,websocket协议,Jmeter连接数据库,测试报告的查看

目录 1、Jmeter插件管理器 1、Jmeter插件管理器用处&#xff1a;Jmeter发展并产生大量优秀的插件&#xff0c;比如取样器、性能监控的插件工具等。但要安装这些优秀的插件&#xff0c;需要先安装插件管理器。 2、插件的下载&#xff0c;从Availabale Plugins中选择&#xff…

服务器(Linux系统的使用)——自学习梳理

root表示用户名 后是机器的名字 ~表示文件夹&#xff0c;刚上来是默认的用户目录 ls -a 可以显示出隐藏的文件 蓝色的表示文件夹 白色的是文件 ll -a 查看详细信息 total表示所占磁盘总大小 一般以KB为单位 d开头表示文件夹 -代表文件 后面得三组rwx分别对应管理员用户-组…

VSCode创建并运行html页面(使用Live Server插件)

目录 一、参考博客二、安装Live Server插件三、新建html页面3.1 选择文件夹3.2 新建html文件3.3 快速生成html骨架 四、运行html页面 一、参考博客 https://blog.csdn.net/zhuiqiuzhuoyue583/article/details/126610162 https://blog.csdn.net/m0_74014525/article/details/13…

设计模式5-策略模式(Strategy)

设计模式5-策略模式 简介目的定义结构策略模式的结构要点 举例说明1. 策略接口2. 具体策略类3. 上下文类4. 客户端代码 策略模式的反例没有使用策略模式的代码 对比分析 简介 策略模式也是属于组件协作模式一种。现代软件专业分工之后的第一个结果是框架语音应用程序的划分。组…

MATLAB-振动问题:单自由度无阻尼振动系统受迫振动

一、基本理论 二、MATLAB实现 令式&#xff08;1.3&#xff09;中A0 2&#xff0c;omega0 30&#xff0c;omega 40&#xff0c;matlab程序如下&#xff1a; clear; clc; close all;A0 2; omega0 30; omega 40; t 0:0.02:5; y A0 * sin( (omega0 - omega) * t /2) .* s…

【源码+文档+调试讲解】牙科就诊管理系统

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本牙科就诊管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息…

计算机网络 访问控制列表以及NAT

一、理论知识 1. 单臂路由 单臂路由是一种在路由器上配置多个子接口的方法&#xff0c;每个子接口代表不同的 VLAN&#xff0c;用于在一个物理接口上支持多 VLAN 通信。此方法使得不同 VLAN 之间可以通过路由器进行通信。 2. NAT (网络地址转换) NAT 是一种在私有网络和公共…

vue+three.js渲染3D模型

安装three.js: npm install three 页面部分代码&#xff1a; <div style"width: 100%; height: 300px; position: relative;"><div style"height: 200px; background-color: white; width: 100%; position: absolute; top: 0;"><div id&…

小阿轩yx-MySQL数据库管理

小阿轩yx-MySQL数据库管理 使用 MySQL 数据库 在服务器运维工作中不可或缺的 SQL &#xff08;结构化查询语句&#xff09;的四种类型 数据定义语言&#xff08;DDL&#xff09;&#xff1a;DROP&#xff08;删除&#xff09;、CREATE&#xff08;创建&#xff09;、ALTER&…

帝国cms定时审核并更新的方法

比如你网站采集了成千上万篇文章&#xff0c;不可能一下子全部放出来的&#xff0c;所以为了模拟人工发布&#xff0c;那么就需要定时审核发布文章内容&#xff0c;本文内容核心解决了更加个性化的逼真模拟人工更新网站内容。 第一&#xff1a;首先要满足你的表中有未审核的数据…

JavaWeb——MySQL:DML

目录 DML&#xff1a;添加&#xff0c;修改&#xff0c;删除表的数据&#xff1b; 1. 添加表的数据 1.1 给所有列添加数据 1.2 给指定列添加数据 1.3 批量添加信息 总结&#xff1a; DML&#xff1a;添加&#xff0c;修改&#xff0c;删除表的数据&#xff1b; 1. 添加表的…

cube-studio开源一站式机器学习平台,在线ide,jupyter,vscode,matlab,rstudio,ssh远程连接,tensorboard

全栈工程师开发手册 &#xff08;作者&#xff1a;栾鹏&#xff09; 一站式云原生机器学习平台 前言 开源地址&#xff1a;https://github.com/tencentmusic/cube-studio cube studio 腾讯开源的国内最热门的一站式机器学习mlops/大模型训练平台&#xff0c;支持多租户&…

微博默认按照最新时间排序

微博默认按照最新时间排序 目前微博会默认按照推荐顺序排序&#xff0c;如果你想要默认按照时间顺序排序的话&#xff0c;可以使用这个油猴脚本。 演示&#xff1a; 脚本安装地址 源代码地址 参考 本项目基于 vite-plugin-monkey 开发 菜单切换&#xff08;useOption&…

设计模式原则——单一职责原则(SPS)

设计模式原则 设计模式示例代码库地址&#xff1a; https://gitee.com/Jasonpupil/designPatterns 单一职责原则&#xff08;SPS&#xff09;&#xff1a; 又称单一功能原则&#xff0c;面向对象五个基本原则&#xff08;SOLID&#xff09;之一原则定义&#xff1a;一个类应…

深度学习工具jupyter创建并检测pytorch环境以及安装工具包

1. 前言 确保已经安装Python和anaconda&#xff08;anaconda一般自带jupyter&#xff09;。然后创建一个jupyter环境&#xff0c;查看启动后的new有没有环境选项。 如果遇到了EnvironmentLocationNotFound:Not such a environment。说明conda环境安装位置有问题&#xff0c;往…

Qt6 windows10下悬浮按钮栏实现

打王者荣耀的时候,你是否有看到中间的按钮是悬浮在屏幕的左右侧,以及中下位置,背景则是一个播放着视频的画面。 从程序的角度来看,它就是实现了一个悬浮按钮栏的功能。当然了,你也可以做成悬浮列表,悬浮下拉框,悬浮xxx等控件。 这里,我们实现在Windows的版本。手机版…

Vue45 scope

scope 限制css的作用范围 用法 <template><div class"demo"><h2 >学生姓名&#xff1a;{{name}}</h2><h2>学生性别&#xff1a;{{sex}}</h2></div> </template><script>export default {name:Student,data…

240624_昇思学习打卡-Day6-张量Tensor

240624_昇思学习打卡-Day6-张量Tensor 今儿扭头回来看看基础&#xff0c;看看最基本的数据结构&#xff0c;张量&#xff08;Tensor&#xff09;。 张量和数组、矩阵非常相似。是MindSpore网络运算中的基本数据结构&#xff0c;本文主要介绍张量和稀疏张量的属性及用法。 文章…