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

五大知识点带你梳理react进阶知识

  • ✉️前言
  • 一、props
    • 1、PropTypes与DefaultProps应用
      • (1)PropTypes
      • (2)defaultProps
    • 2、props,state与render函数
  • 二、React中的虚拟DOM
    • 1、什么是虚拟DOM
      • (1)第一种方案
      • (2)第二种方案
      • (3)第三种方案
    • 2、虚拟DOM中的 Diff 算法
  • 三、React中ref的使用
  • 四、React中的生命周期
    • 1、生命周期函数是什么
    • 2、生命周期图例
  • 五、React中使用CSS动画效果
    • 1、普通用法
    • 2、react-transition-group
      • (1)初次探索
      • (2)进阶探索
  • 六、结束语
  • ️彩蛋

✉️前言

对于 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只停留在表层?五大知识点带你梳理进阶知识_第1张图片

五、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 {
     
}

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

react只停留在表层?五大知识点带你梳理进阶知识_第2张图片

(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;

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

react只停留在表层?五大知识点带你梳理进阶知识_第3张图片

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

六、结束语

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

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

️彩蛋

  • 关注公众号星期一研究室,第一时间关注优质文章,更有面试专栏待你解锁~
  • 如果您觉得这篇文章有帮助到您的的话不妨点赞支持一下哟~~
  • 以上就是本文的全部内容!我们下期见!

你可能感兴趣的:(#,react.js,react.js,javascript,前端,js)