react只停留在表层?五大知识点带你梳理进阶知识

简介: 该文章深入探讨了React进阶主题,包括PropTypes与默认属性的使用、虚拟DOM的工作机制、Refs的高级用法、生命周期方法的详解以及CSS动画在React中的集成技巧。

✉️前言

对于 react 的表层来说,我们可能经常听说的是声明式开发单向数据流组件化方式开发等等。那么,进一步来讲的话,我们还需要了解的是 reactprops ,虚拟 DOMref 以及过渡动画等更多新的知识点。

那在下面的这篇文章中,将来探索关于 react 的进阶知识。

叮,下面开始本文的介绍~🤪

📧一、props

1、PropTypes与DefaultProps应用

(1)PropTypes

react 中,有时候我们要对组件中的某个属性进行格式校验,这个时候我们就需要用到 propTypes下面给出一些常见的例子:

// 表示要对TodoItem这个组件做属性的校验
TodoItem.propTypes = {
   
    // isRequired 表示必须有值
    test: PropTypes.string.isRequired,
    // 表示content的propTypes必须是string类型,那string类型的校验是从PropTypes这个包里面拿到的
    content: PropTypes.string,
    // 表示detail可以是一个number或者string的语法
    detail: PropTypes.arrayOf(PropTypes.number, PropTypes.string),
    // 表示deleteItem必须是一个函数
    deleteItem: PropTypes.func,
    // 表示index必须是一个数字类型
    index: PropTypes.number
}

(2)defaultProps

有时候,对于某个属性来说,我们希望给它个初始值,那这个时候就需要用到 defaultProps示例如下:

TodoItem.defaultProps = {
   
    test: 'hello world'
}

上面的代码表明,当 test 属性没有被赋值时,那么它将被赋予一个初始值,值为 hello world

2、props,state与render函数

react 中,定义一个组件时,经常会看到 propsstaterender 。那他们三者是怎么样的关系呢?

首先我们要想一个问题:为什么数据发生变化,页面就会跟着变化呢?

原因在于,页面是由 render 函数渲染出来的,当数据 state 发生变化时, render 函数就会被重新的执行一次。

同时,当父组件render 函数被运行时,它的子组件render 都将被重新运行。

📨二、React中的虚拟DOM

1、什么是虚拟DOM

(1)第一种方案

传统实现虚拟 DOM 的思路:

  • 先定义 state ,也就是数据;
  • 编写JSX 模板内容;
  • 数据和模板进行结合,生成真是的 DOM ,进而将内容显示到页面上;
  • 如果遇到要替换数据时,则把数据和模板进行结合,生成真实的 DOM ,来替换原始的 DOM

存在缺陷:

  • 第一次生成了一个完整的 DOM 片段;
  • 第二次又生成了一个完整的 DOM 片段;
  • 第二次的 DOM 替换第一次的 DOM ,非常耗费性能。

(2)第二种方案

传统实现虚拟 DOM 的思路改进版:

  • 先定义 state ,即数据;
  • 编写 JSX 模板内容;
  • 数据和模板进行结合,生成真实的 DOM ,并展示;
  • state 的数据发生改变;
  • 继续,把数据和模板进行结合,生成真实的 DOM ,并不是直接替换原始的 DOM
  • 将新的 DOM 和原始的 DOM 做比较,并找出差异
  • 找到新的 Dom 中发生的变化;
  • 只用DOM变化的数据,来替换掉DOM 中的数据。

存在缺陷:

  • 性能的提升并不明显

(3)第三种方案

react 中实现虚拟 DOM 的思路:

  • 先定义 state ,即数据;

  • 编写 JSX 模板内容;

  • 数据和模板进行结合,生成虚拟 DOM (虚拟 DOM 就是一个 JS 对象,用它来描述真实 DOM )。👉(损耗了性能)

    <div id="abc"><span>hello world</span></div>
    ['div', {
         id: 'abc'}, ['span', {
         }, 'hello world']]
    
  • 用虚拟 DOM 的结构生成真实的 DOM ,来进行显示;

  • state 发生变化时,数据 + 模板生成新的虚拟 DOM👉(极大的提升了性能)

<div id="abc"><span>monday</span></div> 
['div', {
   id: 'abc'}, ['span', {
   }, 'monday']]
  • 比较 原始虚拟 DOM新的虚拟 DOM 的区别,找到其中的区别是 span 中的内容;
  • 直接操作 DOM ,改变 span 的内容;
  • 因此, React 的虚拟 DOM 主要经历的过程是: JSXcreateElement → 虚拟 DOMJS 对象 )→ 真实的 DOM

react 虚拟 DOM 的优点:

  • 极大的提升了性能;
  • 它使得跨端应用得以实现,这要谈到 react 中的一个概念,react native
  • react 使用可以编写原生应用,像 AndroidIOS 开发,这些都是操作真实 DOM
  • react 使得编写这些原生应用得以使用。

2、虚拟DOM中的 Diff 算法

  • reactsetState 的性能优化,它会把多次 setState 结合成一次 setState
  • 虚拟 DOM 使用 diff 算法做比较,只在同层做比较,不跨级做比较
  • 同层比对的算法比较简单,而算法简单带来的直接好处就是速度非常快;
  • 虽然可能会造成 DOM 渲染上的一些浪费,但是呢,它也极大的减少了两个虚拟 DOM 之间进行比较时,性能上的消耗。

📩三、React中ref的使用

react 中建议的是,希望我们可以用数据驱动的形式来编写代码,尽量不要操作 DOM 。但有时候,我们在做一些极其复杂业务的时候,比如各种震撼动画,不可避免的还是会用到一些原生的 DOM 标签。因此, ref 帮助我们在 react 中直接获取 DOM 元素的时候来进行使用。

一般情况下,我们尽量不使用 ref 。如果用 ref 时,会出现各种各样的问题。同时,当使用 refsetState 时,要注意一些存在的坑

比如,当 refsetState 相关联使用时,要注意, setState 是一个异步函数,往往会在同步代码执行完毕后再执行异步代码。因此,如果我们希望同步代码执行顺序在 setState 之后时,可以在 setState 接受的第二个参数中,再增加一个回调函数来进行调用,这样就可以达到我们的效果啦!

render() {
   
    return (
        <ul ref={
   (ul) => this.ul = ul}>
            {
   this.getTodoItem()}
        </ul>
    )
}

this.setState((prevState) => ({
   
    list: [...prevState.list, prevState.inputValue],
    inputValue: ''
}), () => {
   
    console.log(this.ul.querySelectorAll('div').length)
});

📦四、React中的生命周期

1、生命周期函数是什么

所谓生命周期函数,指的是在某一个时刻,组件会自动调用执行的函数。那 react 的生命周期都有哪一些呢?

阶段 生命周期 含义
Mounting componentWillMount ①当组件即将被挂载到页面的时刻时自动执行,即在页面挂在之前执行;②只在组件被第一次挂在到页面上才会执行;
Mounting/Updation render 页面挂载时被执行
Mounting componentDidMount 会在组件被挂载到页面之后,自动被执行;只在组件被第一次挂在到页面上才会执行
Updation componentWillReceiveProps ①当一个组件从父组件接收参数;②只要父组件的render函数被执行了,子组件的这个生命周期函数就会被执行;③如果这个组件第一次存在于父组件中,不会执行;④如果这个组件之前已经存在于父组件中,才会被执行;
Updation componentWillUpdate ①组件被更新之前,她会自动执行;②但是它是在shouldComponentUpdate之后被执行,如果shouldComponentUpdate返回true时,它才执行;如果返回false,这个函数就不会被执行了。
Updation componentDidUpdate 组件更新完成之后,它会被执行。
Updation shouldComponentUpdate 组件被更新之前,它会被自动被执行;此生命周期返回一个布尔值
Unmounting componentWillUnmount 当这个组件即将被从页面中剔除的时候,会被执行。

2、生命周期图例

下面用一张图来展示 react 中生命周期的执行效果:

react生命周期

📪五、React中使用CSS动画效果

1、普通用法

我们来看一下,在 react 中,如何使用 css3 所提供的动画效果。具体代码如下:

.show {
   
  animation: show-item 2s ease-in forwards;
}

.hide {
   
  animation: hide-item 2s wase-in forwards;
}

@keyframes show-item {
   
  0% {
   
    oppacity: 0;
    color: red;
  }

  50% {
   
    opacity: 0.5;
    color: green;
  }

  100% {
   
    opacity: 1;
    color: blue;
  }
}

2、react-transition-group

(1)初次探索

有时候,我们可能会想要实现一些很复杂的动画,这个时候 css3 提供的是不够的。因此,我们还需要一点 js 来加以辅助实现更为复杂的动画。这个时候就有谈到 react 中的 react-transition-group 动画。

假设我们想要实现,当点击一个按钮时,一行文字渐隐渐显的实现,那该怎么处理呢?

首先,我们在项目的 src 文件夹下新增一个组件,命名为 App.js具体代码如下:

import React, {
    Component, Fragment } from 'react';
import {
    CSSTransition } from 'react-transition-group';
import './style.css';

class App extends Component {
   
  constructor(props) {
   
    super(props);
    this.state = {
   
      show: true
    }
    this.handleToggle = this.handleToggle.bind(this);
  }

  render() {
   
    return (
      <Fragment>
        {
   /* onEntered指的是在某一个时刻会自动执行的一个函数
            当入场动画结束时,onEntered将会被执行
        */}
        <CSSTransition
          in={
   this.state.show}
          timeout={
   1000}
          classNames='fade'
          unmountOnExit
          onEntered={
   (el) => {
    el.style.color = "blue" }}
          appear={
   true}
        >
          <div>hello</div>
        </CSSTransition>
        <button onClick={
   this.handleToggle}>toggle</button>
      </Fragment>
    )
  }

  handleToggle() {
   
    this.setState({
   
      show: this.state.show ? false : true
    })
  }
}

export default App;

之后新增一个 CSS 文件,命名为 style.css具体代码如下:

/* 入场动画执行的第一个时刻,即刚要入场的这个瞬间 */
/* fade-appear用于实现渐隐渐现的效果 */
.fade-enter,
.fade-appear {
   
  opacity: 0;
}

/* 入场动画执行的第二个时刻,到入场动画执行完成之前的一个时刻 */
.fade-enter-active,
.fade-appear-active {
   
  opacity: 1;
  transition: opacity 1s ease-in;
}

/* 当整个入场动画执行完成之后 */
.fade-enter-done {
   
  opacity: 1;
}

/* 表示出场动画执行的第一个时刻 */
.fade-exit {
   
  opacity: 1;
}

/* 整个出场的过程 */
.fade-exit-active {
   
  opacity: 0;
  transition: opacity 1s ease-in;
}

/* 当整个出场动画执行完成时 */
.fade-exit-done {
   
}

此时我们来看下浏览器的显示效果:

css动画初阶探索

(2)进阶探索

上面我们只是改变了一项数据。现在,如果我们想要点击就新增一项过渡效果,这又该如何处理呢?

我们来改造下 App.js 文件的代码。具体代码如下:

import React, {
    Component, Fragment } from 'react';
import {
    CSSTransition, TransitionGroup } from 'react-transition-group';
import './style.css';

class App extends Component {
   
  constructor(props) {
   
    super(props);
    this.state = {
   
      show: true,
      list: []
    }
    this.handleToggle = this.handleToggle.bind(this);
  }

  render() {
   
    return (
      <Fragment>
        {
   /* onEntered指的是在某一个时刻会自动执行的一个函数
            当入场动画结束时,onEntered将会被执行
        */}
        <TransitionGroup>
          {
   
            this.state.list.map((item, index) => {
   
              return (
                <CSSTransition
                  in={
   this.state.show}
                  timeout={
   1000}
                  classNames='fade'
                  unmountOnExit
                  onEntered={
   (el) => {
    el.style.color = "blue" }}
                  appear={
   true}
                  key={
   index}
                >
                  <div>{
   item}</div>
                </CSSTransition>
            )
            })
          }
        </TransitionGroup>
        <button onClick={
   this.handleToggle}>toggle</button>
      </Fragment>
    )
  }

  handleToggle() {
   
    this.setState((prevState) => {
   
      return {
   
        list: [...prevState.list, 'item']
      }
    })
  }
}

export default App;

此时浏览器的运行效果如下:

css动画进阶探索

对于这种类型的动画来说,我们通过 TransitionGroup 对外层进行包裹,之后通过 CSSTransition 对里层进行包裹,进而达到我们最终的效果。

📮六、结束语

在上面这篇文章中,我们讲解了 react 中的 props ,同时,还简单的了解了虚拟 DOM 的内容。除此之外呢,还学习了 ref 的使用,以及 react 中的酷炫的过渡动画。当然,最为重要的一点是, react 中的生命周期函数

那到这里, react 的进阶知识讲到这里就结束了。不知道小伙伴们对 react 是否又有进一步的认识呢?

🗳️彩蛋

  • 关注公众号星期一研究室,第一时间关注优质文章,更有面试专栏待你解锁~
  • 如果您觉得这篇文章有帮助到您的的话不妨点赞支持一下哟~~😉
  • 以上就是本文的全部内容!我们下期见!🥂🥂🥂
相关文章
|
10天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
7天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2513 16
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
7天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1520 14
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
3天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
9天前
|
编解码 JSON 自然语言处理
通义千问重磅开源Qwen2.5,性能超越Llama
击败Meta,阿里Qwen2.5再登全球开源大模型王座
550 14
|
1月前
|
运维 Cloud Native Devops
一线实战:运维人少,我们从 0 到 1 实践 DevOps 和云原生
上海经证科技有限公司为有效推进软件项目管理和开发工作,选择了阿里云云效作为 DevOps 解决方案。通过云效,实现了从 0 开始,到现在近百个微服务、数百条流水线与应用交付的全面覆盖,有效支撑了敏捷开发流程。
19282 30
|
9天前
|
人工智能 自动驾驶 机器人
吴泳铭:AI最大的想象力不在手机屏幕,而是改变物理世界
过去22个月,AI发展速度超过任何历史时期,但我们依然还处于AGI变革的早期。生成式AI最大的想象力,绝不是在手机屏幕上做一两个新的超级app,而是接管数字世界,改变物理世界。
465 48
吴泳铭:AI最大的想象力不在手机屏幕,而是改变物理世界
|
1月前
|
人工智能 自然语言处理 搜索推荐
阿里云Elasticsearch AI搜索实践
本文介绍了阿里云 Elasticsearch 在AI 搜索方面的技术实践与探索。
18838 20
|
1月前
|
Rust Apache 对象存储
Apache Paimon V0.9最新进展
Apache Paimon V0.9 版本即将发布,此版本带来了多项新特性并解决了关键挑战。Paimon自2022年从Flink社区诞生以来迅速成长,已成为Apache顶级项目,并广泛应用于阿里集团内外的多家企业。
17528 13
Apache Paimon V0.9最新进展
|
1天前
|
云安全 存储 运维
叮咚!您有一份六大必做安全操作清单,请查收
云安全态势管理(CSPM)开启免费试用
361 4
叮咚!您有一份六大必做安全操作清单,请查收