React 学习笔记总结(七)

news2024/11/18 4:23:18

针对React拓展相关的学习。

文章目录

  • 一. React 项目打包
  • 二. React扩展 之 setState两种写法
  • 三. React扩展 之 lazyLoad(懒加载)
  • 四、React的 stateHook
  • 五、React 的 Effect Hook
  • 六、React 的 RefHook
  • 七、React 的 Fragment
  • 八、React 的 Context
  • 九、React 的 PureComponent
    • 1. Component组件的两个问题
    • 2. PureComponent 纯组件
  • 十、React 的 render props
    • 1. 组成父子组件的 两种方式
    • 2. render props 的 使用
  • 十一、React 的 ErrorBoundary
  • 十二、React 组件通信方式总结

一. React 项目打包

安装serve,该库的作用可以将一个静态页面作为一台服务器启动。方便测试打包后的html页面。

# 安装serve
npm i serve
# 执行serve,在对应打包后的目录下,执行serve命令
serve 

二. React扩展 之 setState两种写法

第一种写法:就是传对象。
在这里插入图片描述

setState方法的两个参数:

import React, {Component} from 'react';

export default class Demo extends Component {

    state = {count:0}

    add = () => {
        const {count} = this.state
        // 更新状态 , 第二个参数callback是回调函数
        this.setState({count:count+1},() => {
            // fixme state状态改完,render页面刷新完,才调用该回调函数
        })
        // 因为,setState所调用的形式是异步的。
        console.log('此时state中的count值并没有变化:',this.state.count)
    }

    render() {
        return (
            <div>
                <h1>当前求和为:{this.state.count}</h1>
                <button onClick={this.add}>1</button>
            </div>
        );
    }
}

第二种写法:传递函数。

  • 函数式setState: 好处拿到了state和props。也方便维护。
import React, {Component} from 'react';

export default class Demo extends Component {

    state = {count:0}

    add = () => {
        const {count} = this.state
        // 函数式setState: 好处拿到了state和props
        this.setState((state,props) => {
            console.log('state',state)
            console.log('props',props)
            return {
                count:count+1
            }
        })
        console.log('此时state中的count值并没有变化:',this.state.count)
    }

    render() {
        return (
            <div>
                <h1>当前求和为:{this.state.count}</h1>
                <button onClick={this.add}>1</button>
            </div>
        );
    }
}

使用原则:

  • 如果新状态不依赖于原来状态。 推荐使用对象方式。
  • 如果新状态依赖与原来状态。 推荐使用函数方式。(例如:上面自动+1效果)。

注意:如果需要在setState()执行后获取最新的状态数据,要在第二个callback函数中进行读取操作取。

三. React扩展 之 lazyLoad(懒加载)

一般项目特别大,组件特别多,都会用到懒加载这个东西。

例如:一个页面涉及到了20多个路由页面,但是用户仅仅用了3个,然而,加载的时候缺加载了20多个路由页面,这样就不太好。

所以,就要用懒加载。

案例如下:

  • 通过使用lazy和Suspense来进行操作。
// fixme 1. 引入lazy,Suspense
import React, {Component,lazy,Suspense} from 'react';
import { NavLink, Route} from 'react-router-dom'

// fixme 2. 路由组件不要用引入的方式
// import About from '../2_lazyLoad/About'
// import Home from '../2_lazyLoad/Home'

// fixme 注意: fallback中的内容组件必须是就位的,不能又使用import()函数,所以最好是提前引入
import Load from '../components/Load/Load'

// fixme 3. 定义成函数并且使用import()函数操作
const Home = lazy(() => {
    // 使用import()函数来引入
    return import('../2_lazyLoad/Home')
})
const About = lazy(() => {
    // 使用import()函数来引入
    return import('../2_lazyLoad/About')
})

class Demo extends Component {
    render() {
        return (
            <div style={{textAlign:"center"}}>
                <div style={{textAlign:"center"}}>
                    <h1>React Router Demo</h1>
                </div>
                <div style={{textAlign:"center"}}>
                    {/*{React靠路由跳转}*/}
                    <NavLink to="/about">
                        About
                    </NavLink>
                    <br/>
                    <NavLink to="/home">
                        Home
                    </NavLink>
                </div>
                <div style={{textAlign:"center"}}>
                    {/* fixme 4. 使用Suspense来包裹Route,fallback显示的是加载完成前的操作。注意:fallback中的内容组件必须是就位的,不能又使用import()函数 */}
                    <Suspense fallback={<Load/>}>
                        {/* 注册路由: 注意route和Router区分 */}
                        <Route path="/about" component={About}/>
                        <Route path="/home" component={Home}/>
                    </Suspense>
                </div>
            </div>
        );
    }
}

export default Demo;

四、React的 stateHook

Hook是React 16.8.0版本新增加的一个特性。

可以让函数组件中使用state以及其他的React属性(例如:生命周期钩子函数之类的。)。

三个常用的Hook:

  • State Hook: React.useState()
  • Effect Hook:React.useEffect()
  • Ref Hook:React.useRef()

State Hook的使用:

import React from 'react';

/**
 * 函数式组件
 */
function Index(){

    console.log('组件调用次数是 n + 1 次,第一次进入页面1次,之后render渲染n次。')

    /**
     * React.useState(0): 第一个参数代表初始值
     * 返回值是个数组:第一个是状态state值,第二个是函数(负责更新状态state值)。
     */
    const [count,setCount] = React.useState(0)
    const [name,setName] = React.useState("Tom")

    function add(){
        console.log('+++')
        // setCount第一种写法:(值写法)
        setCount(count + 1)
        // setCount第二种写法:(函数写法) 可以更好维护
        setCount(preCount => (preCount + 1))
    }

    function update(){
        setName('Jerry')
    }

    return (
        <div>
            <h2>当前求和为:{count}</h2>
            <h2>我的名字是:{name}</h2>
            <button onClick={add}>点我 + 1</button>
            <button onClick={update}>修改名字</button>
        </div>
    )
}

export default Index;

五、React 的 Effect Hook

Effect Hook的使用:

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

/**
 * 函数式组件
 */
function Index(){

    const [count,setCount] = React.useState(0)

    /**
     * React.useEffect函数作用:就是实现了类函数中的componentDidMount之类的钩子函数了。
     *  但是用法很不同: 第一个参数(函数):是要执行的函数。 第二个参数(数组):是要监听哪个状态值。
     */
    React.useEffect(()=>{
        let timer = setInterval(()=>{
            setCount(count => count + 1)
        },1000)
        // fixme 此处的返回值就是等于componentWillUnmount
        return () => {
            console.log('@@@')
            clearInterval(timer)
        }
    },[count])

    /**
     * 还有一种情况,像定时器之类的,在离开页面前需要关闭定时器。
     *  一般对象组件就直接在使用componentWillUnmount组件就可以了。
     *
     */
    function  unmount(){
        // 通过使用ReactDOM.unmountComponentAtNode来卸载组件
        ReactDOM.unmountComponentAtNode(document.getElementById('root'))
    }

    function add(){
        setCount(preCount => (preCount + 1))
    }

    return (
        <div>
            <h2>当前求和为:{count}</h2>
            <button onClick={add}>点我 + 1</button>
            <button onClick={unmount}>卸载Root</button>
        </div>
    )

}

export default Index;

可以把 useEffect Hook 看做对象组件如下三个钩子函数的组合:

  • componentDidMount()
  • componentDidUpdate()
  • componentWillUnmount()
语法和说明: 
useEffect(() => { 
  // 在此可以执行任何带副作用操作
  return () => { // 在组件卸载前执行
    // 在此做一些收尾工作, 比如清除定时器/取消订阅等
  }
}, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行

六、React 的 RefHook

类式组件使用ref:

/**
 * 类式组件:
 */
class Index extends React.Component {

    state = {count:0}

    // fixme 创建一个ref
    myRef = React.createRef()

    alertRef = () => {
        alert(this.myRef.current.value)
    }

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

    render() {
        return (
            <div>
                <input type="text" ref={this.myRef}/>
                <h2>当前求和为:{this.state.count}</h2>
                <button onClick={this.add}>点我 + 1</button>
                <button onClick={this.alertRef}>提示</button>
            </div>
        );
    }
}

RefHook的使用:

(1). Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
(2). 语法: const refContainer = useRef()
(3). 作用:保存标签对象,功能与React.createRef()一样

七、React 的 Fragment

Frgament用法:

import React, {Component,Fragment} from 'react';

class Index extends Component {
    render() {
        return (
            // 这样就不用写一个div了。
            <Fragment>
                <input type="text"/>
            </Fragment>
        );
    }
}

export default Index;

空标签的用法:

import React, {Component,Fragment} from 'react';

class Index extends Component {
    render() {
        return (
            // fixme 也可以使用一个空标签
            <>
                <input type="text"/>
            </>
        );
    }
}

export default Index;

Fragment 与 空标签 区别:

  • 作用相同,但是Fragment可以有一个key属性,作为唯一标识使用(只有key属性)。

八、React 的 Context

context是 一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信。

考虑两种情况:

  • 对象式组件 和 函数式组件,不过一般项目中使用了redux就不会使用该方式了。
1) 创建Context容器对象:
	const XxxContext = React.createContext()  
	
2) 渲染子组时,外面包裹xxxContext.Provider, 通过value属性给后代组件传递数据:
	<xxxContext.Provider value={数据}>
		子组件
    </xxxContext.Provider>
    
3) 后代组件读取数据:

	// fixme 第一种方式:仅适用于类组件 
	  static contextType = xxxContext  // 声明接收context
	  this.context // 读取context中的value数据
	  
	// fixme 第二种方式: 函数组件与类组件都可以
	  <xxxContext.Consumer>
	    {
	      value => ( // value就是context中的value数据
	        要显示的内容
	      )
	    }
	  </xxxContext.Consumer>

九、React 的 PureComponent

1. Component组件的两个问题

1. 只要执行setState(),即使不改变状态数据, 组件也会重新render() ==> 效率低。

2. 只当前组件重新render(), 就会自动重新render子组件,纵使子组件没有用到父组件的任何数据。 ==> 效率低。

上面就会导致效率降低的情况。

导致上面情况的发生,因为,Component中的shouldComponentUpdate()钩子函数总是返回true。
在这里插入图片描述

2. PureComponent 纯组件

使用PureComponent
	PureComponent重写了shouldComponentUpdate(), 只有state或props数据有变化才返回true
	注意: 
		只是进行state和props数据的浅比较, 如果只是数据对象内部数据变了, 返回false  
		不要直接修改state数据, 而是要产生新数据
项目中一般使用PureComponent来优化

注意:不要直接修改state数据,直接修改state虽然属性变了,但自身对象地址未发生变化(也就是个浅赋值),而是要产生新数据,不然PureComponent无法检测到。
在这里插入图片描述
还是要注意纯组件失效不更新的情况。

十、React 的 render props

1. 组成父子组件的 两种方式

第一种方式:
在这里插入图片描述
第二种方式:
在这里插入图片描述
注意:第二种方式有瑕疵,那么\<B name={this.state}/\>的this指向的是谁?此处便是缺点。

2. render props 的 使用

// 比较Vue 和 React:
Vue中: 
	使用slot技术, 也就是通过组件标签体传入结构  <A><B/></A>
React中:
	使用children props: 通过组件标签体传入结构
	使用render props: 通过组件标签属性传入结构,而且可以携带数据,一般用render函数属性

在这里插入图片描述

// 其实render prop就是为了解决如下情况:
<A>
  <B>xxxx</B>
</A>
{this.props.children}
问题: 如果B组件需要A组件内的数据, ==> 做不到 

十一、React 的 ErrorBoundary

错误边界(Error boundary):用来捕获后代组件错误,渲染出备用页面,实际上就是有一个出错后能显示的页面。

只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误。

通过getDerivedStateFromError配合componentDidCatch来实现:

class Index extends Component {

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

	// 生命周期函数,一旦后台组件报错,就会触发
	static getDerivedStateFromError(error) {
	    console.log(error);
	    // 在render之前触发
	    // 返回新的state
	    return {
	        hasError: true,
	    };
	}
	// 将错误信息返回后台(需要的话。)
	componentDidCatch(error, info) {
	    // 统计页面的错误。发送请求发送到后台去
	    console.log(error, info);
	}

    render() {
        return (
            <div>
                <h3>组件</h3>
                {this.state.hashError ? <h2>当前不稳定,请稍后重试!</h2> : <Child/>}
            </div>
        );
    }
}

十二、React 组件通信方式总结

在这里插入图片描述

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

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

相关文章

centos配置网卡自动获取ipv4和ipv6地址

环境&#xff1a; os&#xff1a;centos7 1.背景 正常网卡通过dhcp是不会自动获取ipv6地址的&#xff0c;一般手动执行dhclient -6 <网卡名>可以获取。 现在需求是&#xff1a;实现os启动后自动获取到ipv6地址 2.方法 在网卡对应的配置文件/etc/sysconfig/network-sc…

一、初识Node.js

一、初识Node.js 1.什么是Node.js Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js 的官网地址&#xff1a; https://nodejs.org/zh-cn/ 2.Node.js中JavaScript运行环境 注意&#xff1a; 浏览器是 JavaScript 的前端运行环境。Node.js 是 JavaScript 的…

The VMware Authorization Service is not running 解决办法

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java案例分…

ARM惹众怒,美国芯片行业也开始抛弃它,跟随中国芯片支持新架构

ARM曾以为它已经垄断了移动芯片市场&#xff0c;因此可以肆意&#xff0c;甚至还传出计划提高芯片架构授权费的消息&#xff0c;去年还计划限制高通等美国芯片企业自研核心架构&#xff0c;此前它已得罪中国芯片&#xff0c;可以说ARM真正惹了众怒&#xff0c;如此情况下这些芯…

开源文档协作套件CryptPad

本文完成于 2022年 9 月&#xff0c;11月的时候补充了些内容&#xff0c;修改了部分图片&#xff0c;原本是准备发的&#xff0c;不知什么原因又给拖延了&#xff1b; 当时的版是 v5.1.0&#xff0c;而现在最新的版本是 v5.2.1 &#xff1b; 什么是 CryptPad &#xff1f; Cryp…

WEB页面执行shell命令

上面是我的微信和QQ群&#xff0c;欢迎新朋友的加入。1.安装apache服务apt-get install apache22.创建shell脚本cd /var/www/cgi-bin/ vim shell#!/bin/sh alias urldecodesed "s g;s%\\\\xg" | xargs -0 printf "%b" echo "Content-Type: text/html;…

springboot通过controller,dao,service,serviceImpl的基类快速实现各个实体类的增删改查分页等操作

1.pom.xml文件: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/PO…

【1】K8s上部署KubeSphere

目录 1、环境初始化 【1】改名字和主机名解析 【2】时间同步 【3】禁用iptables和firewalld服务&#xff08;三台都要设置&#xff09; 【4】禁用selinux&#xff08;三台都要设置&#xff09; 【5】禁用swap分区 【6】修改linux的内核参数 2、安装docker 【1】安装doc…

化学试剂Silane-PEG-Biotin,硅烷聚乙二醇生物素材料说明

英文名称&#xff1a;Biotin-PEG-Silane 中文名称&#xff1a;生物素-聚乙二醇-硅烷 分子量&#xff1a;1k&#xff0c;2k&#xff0c;3.4k&#xff0c;5k&#xff0c;10k&#xff0c;20k。。。 存储条件&#xff1a;-20C&#xff0c;避光&#xff0c;避湿 用 途&#xff…

RS485 TO ETH (B)无法联网怎么解决?

1 设置下静态IP&#xff0c;例如&#xff1a; RS485 TO ETH (B) 设置为 192.168.1.200 端口号1111&#xff1b; 电脑设置为192.168.1.199 端口号1111&#xff1b; 2 用互联网社区分享的TCP服务器测试下&#xff1a;120.79.100.197 端口号 10002 3 请关闭电脑的所有防火墙&am…

Java 中 List 排序的 3 种方法

在某些特殊的场景下&#xff0c;我们需要在 Java 程序中对 List 集合进行排序操作。比如从第三方接口中获取所有用户的列表&#xff0c;但列表默认是以用户编号从小到大进行排序的&#xff0c;而我们的系统需要按照用户的年龄从大到小进行排序&#xff0c;这个时候&#xff0c;…

1.1.1信号的概念、描述及分类

目录 1.信号的概念 2.描述 3.分类 3.1确定信号和随机信号 ​3.2连续信号和离散信号​​​​​​​ 两者之间存在这样一种关系 3.3周期信号和非周期信号 3.4能量信号和功率信号 一些例题 1.信号的概念 信号是表示消息的 物理量 &#xff0c;如电信号可以通过 幅度 、 …

23.指针数组的概念,定义方法

1.二维数组 二维数组有行有列&#xff0c;二维数组可以看成由多个一维数组构成的&#xff0c;是多个一维数组的集合&#xff0c;可以认为二维数组的每一个元素都是一个一维数组。 #include<stdio.h> int main() {int a[3][5];printf("a%p\n",a);printf("…

Zabbix与乐维监控对比分析(八)——其他功能篇

前面我们详细介绍了Zabbix与乐维监控的架构与性能、Agent管理、自动发现、权限管理、对象管理、告警管理、可视化、图形图表及网络功能方面的对比分析&#xff0c;接下来我们将对二者其他功能进行对比分析。 本篇是Zabbix与乐维监控对比分析专题系列文章的第八篇&#xff0c;也…

Visual Studio Code快捷键的使用-RK3568开发

在 Visual Studio Code 软件中使用快捷键可以增加自身的效率&#xff0c;一些常用的快捷键如下所 示&#xff1a; F1 打开可以输入命令 F2 重命名变量&#xff0c;方便重构 F5 运行和调试代码 F12 去到定义的地方 shiftF12 查找所有引用 ctrlg 会让你输入数字&#xff0c;快速定…

SpringBoot2源码1-嵌入式Tomcat启动和@SpringBootApplication注解原理

1. 测试案例 1.1 引入依赖 <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.5</ve…

看完RabbitMQ了的几种消息模型,我对RabbitMQ有了新的认识

前言&#xff1a;大家好&#xff0c;我是小威&#xff0c;24届毕业生&#xff0c;曾经在某央企公司实习&#xff0c;目前在某税务公司。前面已经记录了两种消息模型知识&#xff0c;因此本篇文章将记录和分享剩下的RabbitMQ几种消息模型相关知识点。 本篇文章记录的基础知识&am…

锁策略和synchronized

1.常见的锁策略&#xff08;1&#xff09;乐观锁 和 悲观锁乐观锁&#xff1a;预测锁竞争的情况不激烈&#xff08;工作量较少&#xff09;悲观锁&#xff1a;预测锁竞争的情况很激烈&#xff08;工作量较多&#xff09;&#xff08;2&#xff09;轻量级锁 和 重量级锁轻量级锁…

IDEA Alibaba代码格式化(EclipseCodeFormatter)

1.阿里模板下载地址https://github.com/alibaba/p3c/tree/master/p3c-formatter2.下载阿里配置文件&#xff08;eclipse-codestyle.xml&#xff09;&#xff0c;因为此文件是针对ecplice的&#xff0c;在IDEA中使用配置文件&#xff0c;需要安装Eclipse Code Formatter插件3.配…

文档控件 Aspose.PDF for Java 授权须知

Aspose.PDF是一款高级PDF处理API&#xff0c;可以在跨平台应用程序中轻松生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现&#xff0c;保护和打印文档。无需使用Adobe Acrobat。此外&#xff0c;API提供压缩选项&#xff0c;表创建和处理&#xff0c;图形和图像功能&…