React 并发功能体验(前端的并发模式)


Posted in Javascript onJuly 01, 2021

React 是一个开源 JavaScript 库,开发人员使用它来创建基于 Web 和移动的应用程序,并且支持构建交互式用户界面和 UI 组件。React 是由 Facebook 软件工程师 Jordan Walke 创建,React 的第一个版本在七年前问世,现在,Facebook 负责维护。React框架自首次发布以来,React 的受欢迎程度直线飙升,热度不减。
2020 年 10 月,React 17 发布了,但令人惊讶的是——“零新功能”。当然,这并不是真的表示没有任何新添加的功能,让广大程序员使用者兴奋。事实上,这个版本为我们带来了很多重大功能的升级及16版本的bug修复,并推出了:Concurrent Mode 和Suspense。
虽然这两个功能尚未正式发布,这些功能已提供给开发人员进行测试。一旦发布,它们将改变 React 呈现其 UI 的方式,从而达到双倍提高性能和用户体验。

简要说明, Concurrent Mode 和Suspense 可以使用户无缝处理数据加载,加载状态,用户界面操作更加平滑和无缝切换。 在Concurrent Mode 下,React可以暂停高消耗的,非紧急的组件的渲染,并聚焦在更加紧迫的任务处理,如UI 渲染,始终保持应用为可响应式,避免白屏,卡顿等现象。

本文主要分享深入了解Concurrent Mode 和Suspense 模式下的数据提取功能。

为什么需要 Concurrent Mode?

众所周知,JavaScript 框架或库是单线程的工作。因此,当一个代码块运行时,其余的块必须等待执行。无法并发执行多线程工作。界面渲染也是一样的。
一旦 React 开始渲染某些东西,无法中断直到运行完成。React 开发人员将这种渲染称为“阻塞渲染”。 这种阻塞渲染会创建一个不稳定的用户界面,并且随时可能停止响应。

具体问题

假如,我们需要显示一个很长的可选列表用于过滤产品的应用程序。我们使用搜索框用于过滤记录,设计方案是当用户点击搜索按钮后,用户界面需要重新刷新列出相关联的数据。

如果列表过长,数据过多,UI“卡顿”,即渲染对用户可见。这种卡顿也会大大降低产品性能。开发人员可以使用一些技术,如节流和防抖,这些技术会有一定帮助,但不是完美的解决方案。
节流限制特定函数被调用的次数。使用节流,我们可以避免重复调用昂贵和耗时的API或函数。这个过程能够提高性能,尤其是在用户界面上呈现信息。

防抖会在预定的时间内忽略对函数的调用。函数调用仅在经过预定时间后进行。

下图描述了卡顿现象:
在等待非紧急 API 调用完成时,UI 卡顿,从而阻止呈现用户界面。解决方案是使用并发模式进行可中断渲染。

React 并发功能体验(前端的并发模式)

无中断渲染

通过可中断渲染,React.js 在处理和重新渲染列表时不会阻塞 UI。它通过暂停琐碎的工作、更新 DOM 并确保 UI 不会卡顿,使 React.js 更加细化。React 使用用户输入并行更新或重绘输入框。React 使用用户输入并重绘输入框并行执行。它还更新内存中的列表。React 完成更新后,它会更新 DOM 并在用户的显示器上重新呈现列表。本质上,无中断渲染使 React 能够“多任务”。此功能提供了更流畅的 UI 体验。

并发模式

并发模式是一组功能,可帮助 React 应用程序保持响应并平滑地适应用户的设备和网络速度能力。并发模式将其拥有的任务划分为更小的块。 React 的调度程序可以挑选并选择要执行的作业。作业的调度取决于它们的优先级。通过对任务进行优先级排序,它可以停止琐碎或不紧急的事情,或者进一步推动它们。 React 始终将用户界面更新和渲染放在首位。

使用并发模式,我们可以:

  • 控制首次渲染过程
  • 优先处理渲染过程
  • 暂停和恢复组件的渲染
  • 缓存和优化组件的运行时渲染
  • 隐藏显示内容直到需要展示时

随着 UI 渲染,并发模式改进了对传入数据的响应,懒加载控件,异步处理过程。并发模式保证了用户界面始终处于激活状态,并且持续在后台更新数据,并发模式也始终使用React 的两个钩挂:useTransitionuseDeferredValue

使用useDeferredValue Hook

useDeferredValue Hook 的定义如下:

const deferredValue = useDeferredValue(value, { timeoutMs: <some value> });

此命令设置值在timeoutMs中设置的时间后“滞后”。 用户界面是必须立即更新还是必须等待数据,该命令使用户界面保持激活状态和响应性,该Hook避免了 UI 卡顿,并始终保持用户界面响应,以保持获取数据滞后的较小成本。

使用 Transition Hook

useTransition Hook React 中主要用于挂起的Hook,假设这样的场景下:其中有一个带有用户名按钮的网页。只需点击一个按钮,网页就会在屏幕上显示用户的详细信息。
假设用户首先单击一个按钮,然后单击下一个。屏幕要么变成空白,要么我们在屏幕上看到一个微调器。如果获取详细信息花费的时间太长,用户界面可能会冻结。
useTransition 方法返回两个Hook的值:startTransition isPending。定义的语法如下:

const [startTransition, isPending] = useTransition({ timeoutMs: 3000 });

startTransition 定义的语法:

<button disabled={isPending}  
  startTransition(() => {  
        <fetch Calls>  
  });  
  </button>  
  {isPending? " Loading...": null}

使用 useTransition 钩子,React.js 继续显示没有用户详细信息的用户界面,直到用户详细信息准备好,但 UI 是响应式的。React 优先考虑用户界面,以在并行获取数据时保持响应。

为获取数据的Suspense

SuspenseReact与并发模式一起引入的另一个实验性功能。Suspense使组件能够在渲染前等待一段预定的时间。
Suspense的主要作用是从组件异步读取数据,而无需担心数据的来源。Suspense最适合延迟加载的概念。Suspense允许数据获取库通知React数据组件是否可以使用。在必要的组件准备就绪之前,React不会更新 UI。

使用Suspense的好处:

1.数据获取库和React组件之间的集成

2.控制视觉加载状态

3.避免竞争条件

Spinner组件的基本语法如下:

import Spinner from './Spinner';  
    <Suspense fallback={<Spinner />}>  
      <SomeComponent />  
</Suspense>

Concurrent Mode中使用的Suspense允许耗时的组件在等待数据的同时开始渲染。同时显示占位符。这种组合产生了更流畅的UI体验。

Suspense 和 懒加载组件

React.lazy是一个新功能,它使React.js能够延迟加载组件。懒加载意味着仅在需要时才加载组件(检索和呈现它们的代码)。他们会优先考虑最关键的用户界面组件。React开发人员建议将懒加载组件包装在Suspense组件中。
这样做可确保组件在渲染时不会出现“不良状态”。用户界面在整个过程中保持响应,并带来更流畅的用户体验。

启用并发模式

要启用并发模式,请安装最新的测试版本。安装 React 的先决条件是节点数据包管理器 (npm)。要安装测试版本,请执行以下命令:

npm install react@experimental react-dom@experimental

要测试是否设置了测试版本,请创建一个示例 React 应用程序。没有测试功能的渲染代码如下:

import * as React from 'react';  
  import { render } from 'react-dom';  
  render(<App />, document.getElementById('root'));

并发模式的,具体代码如下:

import * as React from 'react';  
    import { createRoot } from 'react-dom';  
createRoot(document.getElementById('root')).render(<App />);

这将为整个应用程序启用并发模式。React 将渲染调用分为两部分:

  1. 创建根元素
  2. 使用渲染调用

目前,React 计划维护三种模式:

  1. 传统模式是向后兼容的传统或当前模式
  2. 阻塞模式是并发模式开发的中间阶段
  3. 并发模式

阻塞模式是使用createBlockingRoot 调用来替换createRoot 调用,在并发模式的开发情况下,阻塞模式为开发者提供了机会来修复bug或解决问题。

React 官方文档中也说明了每种模式支持的功能:

React 并发功能体验(前端的并发模式)

示例应用:

本文也创建了一个测试程序来验证并发模式和其他模式的用法和效果。本文以像素应用为例在150*150的画布上随机分布像素并包含一个搜索框,每次用户点击搜索框时候,画布会重新渲染自己。
即使UI 界面无法在并发模式下渲染,用户输入也不会停止更新。像素画布在处理完成后重新渲染。在传统模式下,快速键入时,UI 会停止,有时会在再次渲染画布之前停止。用户输入也会停止并且不会更新。

构建像素应用程序的主要文件是 canvas.js。我们还制作了一个输入框,用户可以在其中输入任何内容。每次按下一个键都会重新渲染像素画布。

代码示例:Index.js

import React from "react";  
    import ReactDOM from "react-dom";  
    import App from "./App";  
    // Traditional or non-Concurrent Mode react  
    const rootTraditional = document.getElementById("root");  
    ReactDOM.render(<App caption="Traditional or Block Rendering" />,  
    rootTraditional);  
    // Concurrent Mode enabled  
    const rootConcurrent = document.getElementById("root-concurrent");  
    ReactDOM.createRoot(rootConcurrent).render(<App caption="Interruptible  
Rendering"   />);

App.js

import React, { useState, useDeferredValue } from "react";  
  import "./App.css";  
  import { Canvas } from "./Canvas";  
  export default function App(props)  
  { const [value, setValue] = useState("");  

 //This is available only in the Concurrent mode.

    const deferredValue = useDeferredValue(value, {  
      timeoutMs: 5000  
    });  

    const keyPressHandler = e => {  
      setValue(e.target.value);  
    };  

    return (  
      <div className="App">  
        <h1>{props.caption}</h1>  
        <input onKeyUp={keyPressHandler} />  
        <Canvas value={deferredValue} />  
      </div>  
    );  
  }

Canvas.js

import React from "react";  
   const CANVAS_SIZE = 70;  
   const generateRandomColor = () => {  
    var letters = "0123456789ABCDEF";  
    var color = "#";  
    for (var i = 0; i < 6; i++) {  
      color += letters[Math.floor(Math.random() * 16)];  
    }  
    return color;  
  };  
   const createCanvas = (rows, columns) => {  
    let array = [];  
    for (let i = 0; i < rows; i++) {  
      let row = [];  
      for (let j = 0; j < columns; j++) {  
        row.push(0);  
      }  
      array.push(row);  
    }  
    return array;  
  };  
   //This is the square with the pixels  
  const drawCanvas = value => {  
    const canvas = createCanvas(CANVAS_SIZE, CANVAS_SIZE);  
    return canvas.map((row, rowIndex) => {  
      let cellsArrJSX = row.map((cell, cellIndex) => {  
        let key = rowIndex + "-" + cellIndex;  
        return (  
         <div  
            style={{ backgroundColor: generateRandomColor() }}  
            className="cell"  
            key={"cell-" + key}  
          />  
        );  
      });  
      return (  
        <div key={"row-" + rowIndex} className="canvas-row">  
          {cellsArrJSX}  
        </div>  
      );  
    });  
  };  
  export const Canvas = ({ value }) => {  
    return (  
     <div>  
        <h2 style={{ minHeight: 30 }}>{value}</h2>  
       <div className="canvas">{drawCanvas(value)}</div>  
     </div>  
   );  
 };

Index.html

<!DOCTYPE html>  
  <html lang="en">  
    <head>  
      <meta charset="utf-8" />  
      <meta  
        name="viewport"  
        content="width=device-width, initial-scale=1, shrink-to-fit=no"  
      />  
      <meta name="theme-color" content="#000000" />  
      <title>React App Concurrent Mode</title>  
    </head>  
    <body>  
      <noscript>  
     You need to enable JavaScript to run this app.  
      </noscript>  
      <div id="container">  
        <div id="root" class="column"></div>  
        <div id="root-concurrent" class="column"></div>  
      </div>  
    </body>  
  </html>

运行示例

让我们看看我们的代码。我们看到的第一个屏幕是初始屏幕。使用传统或块渲染是现在React 的做法。可中断渲染是并发模式的测试功能。我们先看看传统的渲染工作。

React 并发功能体验(前端的并发模式)

像素画布在每次击键时重新渲染。在传统渲染中,整个 UI 会在每次击键时暂停,直到它可以重新渲染屏幕。在此期间,即使我们继续打字,用户输入不会更新。

下图显示可中断渲染。在可中断渲染中,用户可以继续输入。在为每次击键并行重新渲染画布时,UI 不会停止或停止。

React 并发功能体验(前端的并发模式)

重新渲染完成后,React 会更新 UI。虽然在静态截图中很难看到,但我们可以看到网格在变化,但用户仍然可以打字而不会出现 UI 卡顿的情况。

React 并发功能体验(前端的并发模式)

总结

在本文中,我们研究了 React 的测试并发功能和 Suspense。使用并发模式,React.js 始终保持用户界面响应。它将应用程序的任务分解为更小的块,并允许对用户界面任务进行优先级排序。因此,此模式可提供更流畅和无缝的用户体验,并提高应用程序的整体性能。

结合并发模式,Suspense 允许用户界面保持响应。同时,数据获取等繁重耗时的任务可以并行完成,从而提供整体无缝体验。

有关并发模式的完整详细信息可在 React 官方文档中了解。
随着React版本的改进, React框架越来越被更多的中国前端开发者所熟知并且广泛应用到他们的项目开发中。是继续Vue.js 后又一备受欢迎的前端主流框架,现在也因此衍生除了很多支持与React框架集成的功能工具, 如前端报表ActiveReportsJS控件,提供了与 React 直接集成的在线编辑器和报表展示工具,完善前端的数据展示功能。

到此这篇关于React 并发功能体验-前端的并发模式已经到来的文章就介绍到这了,更多相关React 并发功能内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
基于jquery实现控制经纬度显示地图与卫星
May 20 Javascript
js事件监听器用法实例详解
Jun 01 Javascript
js实现input框文字动态变换显示效果
Aug 19 Javascript
jquery实现定时自动轮播特效
Dec 10 Javascript
javascirpt实现2个iframe之间传值的方法
Jun 30 Javascript
jQuery实现的导航下拉菜单效果
Jul 04 Javascript
JavaScript中的遍历详解(多种遍历)
Apr 07 Javascript
微信小程序表单验证错误提示效果
May 19 Javascript
jquery实现一个全局计时器(商城可用)
Jun 30 jQuery
Vue-cli创建项目从单页面到多页面的方法
Sep 20 Javascript
ES6 Symbol在对象中的作用实例分析
Jun 06 Javascript
vue组件是如何解析及渲染的?
Jan 13 Vue.js
vue中利用mqtt服务端实现即时通讯的步骤记录
Jul 01 #Vue.js
react中的DOM操作实现
Jun 30 #Javascript
elementui的el-popover修改样式不生效的解决
react使用antd的上传组件实现文件表单一起提交功能(完整代码)
vue+element ui实现锚点定位
Jun 29 #Vue.js
vue实现锚点定位功能
适合后台管理系统开发的12个前端框架(小结)
You might like
测试您的 PHP 水平的题目
2007/05/30 PHP
php 遍历数据表数据并列表横向排列的代码
2009/09/05 PHP
phpphp图片采集后按原路径保存图片示例
2014/02/18 PHP
分享PHP计算两个日期相差天数的代码
2015/12/23 PHP
PHP时间函数使用详解
2019/03/21 PHP
取得窗口大小 兼容所有浏览器的js代码
2011/08/09 Javascript
javascript的渐进增强与平稳退化浅谈
2013/11/12 Javascript
JavaScript实现在数组中查找不同顺序排列的字符串
2014/09/26 Javascript
javascript中定义类的方法详解
2015/02/10 Javascript
使用bootstrapValidator插件进行动态添加表单元素并校验
2016/09/28 Javascript
关于webuploader插件使用过程遇到的小问题
2016/11/07 Javascript
基于react框架使用的一些细节要点的思考
2017/05/31 Javascript
Vue-router 类似Vuex实现组件化开发的示例
2017/09/15 Javascript
js数组方法reduce经典用法代码分享
2018/01/07 Javascript
vue、react等单页面项目部署到服务器的方法及vue和react的区别
2018/09/29 Javascript
微信小程序实现页面分享onShareAppMessage
2019/08/12 Javascript
微信公众号服务器验证Token步骤图解
2019/12/30 Javascript
详解微信小程序轨迹回放实现及遇到的坑
2021/02/02 Javascript
[01:18]一目了然!DOTA2DotA快捷操作对比第一弹
2014/07/01 DOTA
使用70行Python代码实现一个递归下降解析器的教程
2015/04/17 Python
通过Python实现自动填写调查问卷
2017/09/06 Python
Python 批量合并多个txt文件的实例讲解
2018/05/08 Python
pandas分别写入excel的不同sheet方法
2018/12/11 Python
Django保护敏感信息的方法示例
2019/05/09 Python
Django  ORM 练习题及答案
2019/07/19 Python
pytorch之inception_v3的实现案例
2020/01/06 Python
Python中关于logging模块的学习笔记
2020/06/03 Python
Python爬虫headers处理及网络超时问题解决方案
2020/06/19 Python
Notino罗马尼亚网站:购买香水和化妆品
2019/07/20 全球购物
应届生自我鉴定
2013/12/11 职场文书
工商管理专业大学生职业生涯规划范文
2014/03/09 职场文书
职业生涯规划书怎么写?
2014/09/14 职场文书
个人整改方案范文
2014/10/25 职场文书
总结Python常用的魔法方法
2021/05/25 Python
node.js使用express-fileupload中间件实现文件上传
2021/07/16 Javascript
python manim实现排序算法动画示例
2022/08/14 Python