React性能优化(完整版)

2023-11-16

  • 我的博客
  • http://wangxince.site/my-demo-markdown/

React 性能优化

1.减少 render 次数

shouldComponentUpdate PureComponent

shouldComponentUpdate(nextProps,nextState) {
return !this.props.xxx === nextProps.xxx
}
// PureComponent 自动浅对比

React.Memo

// 1.当props变化的时候才会重新渲染 浅层对比
function Component(props) {}
const MyComponent = React.memo(Component);
// 2.自定义比较对比Props 如果相等返回true 否则返回false
function MyComponent(props) {}
export default React.memo(MyComponent, (prevProps, nextProps) => boolean);

2.减少函数的重新执行导致的渲染: useCallback

<button onClick={props.onClick}>改标题</button>
// 组件的每次渲染都会重新创建一个新的函数 因此函数的引用地址发生了变化
// 函数会重新开始执行 倒是子组件重新渲染
// 解决办法就是在函数没有改变的时候,重新渲染的时候保持两个函数的引用一致
const memoizedCallback = useCallback(()=>{}, [])
<Child onClick={memoizedCallback} name="xxx" />

3.缓存计算量比较大的函数结果: useMemo

  • 如果没有提供依赖项数组,useMemo 在每次渲染时都会计算新的值
  • 计算量如果很小的计算函数,也可以选择不使用 useMemo,因为这点优化并不会作为性能瓶颈的要点,反而可能使用错误还会引起一些性能问题
const base = useMemo(fn, []);

4.其他优化

1.在 render 渲染函数中不要进行复杂的副作用(数组排序 等等)

2.减少不必要的嵌套

3.虚拟列表

  • https://usehooks-ts.com/react-hook/use-intersection-observer

4.惰性渲染 && 惰性函数

  • 惰性加载表示函数执行的分支只会在函数第一次调用的时候执行。在第一次调用的过程中。
  • 该函数被覆盖为另一个按照合适的方式执行的函数。这样任何对原函数的调用就不用再经过执行的分支了
#
 var timeStamp = null;
  function getTimeStamp() {
    if (timeStamp) {
      return timeStamp
    }
    // 直接为外界的变量赋值
    timeStamp = new Date().getTime()
    return timeStamp;
  }
  console.log(getTimeStamp());
  console.log(getTimeStamp());
  console.log(getTimeStamp());
  console.log(getTimeStamp());
# 自执行函数 避免污染全局变量
  var getTimeStamp = (function () {
    var timeStamp = null;
    return function () {
      if (timeStamp) {
        return timeStamp;
      }
      timeStamp = new Date().getTime()
      return timeStamp;
    }
  })()
# 第一次只是在给函数重新定义 第二次执行时候才生效
 var getTimeStamp = function () {
    var timeStamp = new Date().getTime()
    getTimeStamp = function () {
      return timeStamp
    }
    return getTimeStamp()
  }
# element ui 源码 处理 dom 事件
export const on = (function() {
  if (!isServer && document.addEventListener) {
    return function(element, event, handler) {
      if (element && event && handler) {
        element.addEventListener(event, handler, false);
      }
    };
  } else {
    return function(element, event, handler) {
      if (element && event && handler) {
        element.attachEvent('on' + event, handler);
      }
    };
  }
})();
#
   function test(num) {
    switch (num) {
      case 1:
        test = () => 1
        break;
      case 2:
        test = () => 2
        break;
      case 3:
        test = () => 3
        break;
      default:
        test = () => null
        break;
    }
    return test()
  }
  console.log(test(null)); // null

5.减少使用箭头函数 => 实例方法

  • 使用箭头函数的情况下,每次组件的重新渲染都创建新的事件处理程序,这会导致子组件重新渲染
// 1.class
<ComplexComponent onClick={evt => onClick(evt.id)} otherProps={values} />;
class MyComponent extends Component {
  render() {
    <ComplexComponent onClick={this.handleClick} otherProps={values} />;
  }
  handleClick = () => {};
}
// 2.hooks 使用useCallback包裹
const handleClick = useCallback(() => {}, []);
return <ComplexComponent onClick={handleClick} otherProps={values} />;
// 3.当状态很多时候
function useRefProps<T>(props: T) {
  const ref = useRef < T > props;
  // 每次渲染更新props
  useEffect(() => {
    ref.current = props;
  });
}

function MyComp(props) {
  const propsRef = useRefProps(props);
  // 现在handleClick是始终不变的
  const handleClick = useCallback(() => {
    const { foo, bar, baz, bazz, bazzzz } = propsRef.current;
  }, []);
}
// 4.class需要bind的时候
// 不要这样 <input type="button" value="Click" onClick={this.handleButtonClick.bind(this)} />
<input type="button" value="Click" onClick={this.handleButtonClick} />;
  constructor() {
    this.state = {
      name: "Mayank"
    }
    this.handleButtonClick = this.handleButtonClick.bind(this)
  }

6.使用 Immutable.js

7.简化 state 和 props

  • 不是所有数据都需要放在 state 里面
  • 如果需要组件响应它的变动, 或者需要渲染到视图中的数据才应该放到 state 中
  • 这样可以避免不必要的数据变动导致组件重新渲染

8.颗粒化组件

  • vue 不需要 shouldComponentUpdate 会自动优化
  • 但是如果太过耦合 只要要任意一个属性值变动就会重新渲染整个组件
  • 应该将数据隔离抽取到单一职责的组件
  • 越细粒度的组件,可以收获更高的性能优化效果

8.懒加载异步组件

  • lazy Suspense
  • 减少主包体积 减少网络带宽
if (this.props.name == 'Mayank') {
  ComponentToLazyLoad = lazy(() => import('./mayankComponent'));
} else if (this.props.name == 'Anshul') {
  ComponentToLazyLoad = lazy(() => import('./anshulComponent'));
}
<div>
  <h1>This is the Base User: {this.state.name}</h1>
  <Suspense fallback={<div>Loading...</div>}>
    <ComponentToLazyLoad />
  </Suspense>
</div>;

8.用 Fragment 代替自己最外层写的元素

9.复杂变动的组件+Key

  • 并不是只有 map 渲染的时候才能写 key
  • element 等组件库会将一些 API 利用 computed 缓存(computed 只有当 props 和 data 中的变量变化的时候才会重新缓存)
  • vue 的 diff 算法有时候自动计算会直接缓存
    • (比如你写了两个 El-Button 这时候 diff 算法将他们当成一个,而组件库内部的 computed 没有重新计算)
    • 此时就可能产生值变化 但是表单的 API 未变化的 bug
    • 这时候就需要给其加不同的 key

10.避免使用内联样式

  • <b style={{“backgroundColor”: “blue”}}>Welcome to Sample Page

11.防流节抖

12.CDN

13.gzip 压缩

http{
  gzip on;                      #开启gzip功能
  gzip_types *;                 #压缩源文件类型,根据具体的访问资源类型设定
  gzip_comp_level 6;            #gzip压缩级别
  gzip_min_length 1024;         #进行压缩响应页面的最小长度,content-length
  gzip_buffers 4 16K;           #缓存空间大小
  gzip_http_version 1.1;        #指定压缩响应所需要的最低HTTP请求版本
  gzip_vary  on;                #往头信息中添加压缩标识
  gzip_disable "MSIE [1-6]\.";  #对IE6以下的版本都不进行压缩
  gzip_proxied  off;            #nginx作为反向代理压缩服务端返回数据的条件
}

14.webpack 拆包

css 抽离

plugins: [
   new MiniCssExtractPlugin({
     // 对输出的css文件进行重命名
     filename: 'css/built.css'
   }),
   // 压缩css
   new OptimizeCssAssetsWebpackPlugin()
]

#
  {
        test: /\.css$/,
        use: [ 'file-loader']
             ['file-loader?name=[name].bundle[hash].css']
  },

js 抽离

 output: {
    filename: 'js/[name].js',
    path: path.resolve(__dirname, 'dist'),
  },

代码切割

1. 多入口 自动打包多个文件
   entry: {
    'jquery': './src/index.js',
    'angular': './src/2.js'
  },
2. 异部的chunk
   require.ensure([],function(_require){
     _require('./xxx')
   })
  import('./2.css').then(() => {
    ...
  })
}
#
3.
optimization: {
  splitChunks: {
    chunks: 'all'
  }
}
#
externals: {
  jquery: 'jQuery'
}
引入cdn

dll

#
硬链接一个 包,再手动scrit引入这个包 之后webpack就不用编译了
#
yarn add add-asset-html-webpack-plugin
webpack --config webpack.config.dll.js && webpack
# 文件路径
  webpack.config.js
  webpack.config.dll.js
  dist
     index.html
  src
  public
  dll
     jquery
     manifest.json
# webpack.config.js
const path = require('path')
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
module.export = {
  ...
  externals: {
    jquery: 'jQuery'
  },
  plugins:[
    new HtmlWebpackPlugin({
      template: './index.html',
      filename: 'index.html',
      minify: { removeComments: true }
    }),
    // 告诉webpack哪些库不参与打包,同时使用时的名称也得变~
    new webpack.DllReferencePlugin({
        manifest: resolve(__dirname, 'dll/manifest.json')
    }),
    // 将某个文件打包输出去,并在html中自动引入该资源
    new AddAssetHtmlPlugin({
       filepath: path.resolve(__dirname, 'dll/jquery.js'),
       publicPath: '../dll',
       outputPath: 'vendor',
    }),
  ]
}
# webpack.config.dll.js
const path = require('path');
const webpack = require('webpack')
module.exports = {
  entry: {
    jquery: ['jquery'],
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'dll'),
    library: '[name]_[hash]'
  },
  plugins: [
    // 打包生成一个 manifest.json --> 提供和jquery映射
    new webpack.DllPlugin({
      // 映射库的暴露的内容名称 和 library 相同
      name: '[name]_[hash]',
      path: path.join(__dirname, 'dll/manifest.json'),
    })
  ],
  mode: 'production'
};
externals: {
    jquery: 'jQuery'
},
new webpack.ProvidePlugin({
   $: path.resolve(path.join(__dirname, 'dll/jquery.js'))
}),

其他 cli 集成

  chainWebpack: function(config, { webpack }) {
    config.merge({
      optimization: {
        splitChunks: {
          chunks: 'all',
          minSize: 30000,
          minChunks: 3,
          automaticNameDelimiter: '.',
          cacheGroups: {
            vendor: {
              name: 'vendors',
              test({ resource }: any) {
                return /[\\/]node_modules[\\/]/.test(resource);
              },
              priority: 10,
            },
          },
        },
      },
    });
  },
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

React性能优化(完整版) 的相关文章

  • 停止所有 JavaScript 执行

    是否有一个相当于 php die 函数的 javascript 可以停止所有 javascript 包括将来的 ajax 请求回调 超时等 运行 注意 我无法在调试器中使用断点 因为 bug 存在于 ie8 中 并且调试器会阻止您在断点处向
  • 如何使用 vue-toastification

    我刚刚将在 vue 3 中创建的项目迁移到 nuxt 3 以前我使用了 vue toastification 模块 但现在我不知道如何正确导入它 我的代码使用这个模块 import useToast POSITION from vue to
  • 无法使用服务帐户查询 Google Search Console API

    我需要使用服务帐户从 Google Search Console 网站管理员工具 检索一些数据 到目前为止我已经能够检索到access token对于我需要附加到请求的 url 的服务帐户 问题是我找不到办法这样做 这是我正在使用的代码 f
  • 静态方法而不是原型方法Javascript

    当在类中调用实例函数时 对象的每个实例都会获得自己的函数副本 但在原型方法和静态方法中不会创建副本 它们属于类 所以如果它们都没有创建其函数的副本 那么为什么如果我们不想复制 可以简单地使用原型方法 那么我们是否有静态函数 我有点困惑 如果
  • 如何从图书馆创建承诺

    我对此感到困惑 因为到目前为止我发现的每个教程都假设我可以编辑库代码 或者库只有回调或回调作为最后一个参数 我正在使用的库的每个功能都设置为function successCallBack result FailCallBack error
  • 使用带有代码分割的汇总时,有什么方法可以保留包的目录结构吗?

    Context 给定这样的项目结构 src a module js b module js util js 两者都在哪里module js文件导入util js 使用以下配置 export default experimentalCodeS
  • 如何通知 AngularJS 表单已由 jQuery 外部填写?

    我在 AngularJS 中有一个页面 其中有一个包含一些字段的表单 加载该页面后 我想要一个书签 单击该书签可根据配置文件中的数据填充字段 正在使用一个 JS 文件 该文件使用 jquery 来填充表单中的数据 当我做 id val ab
  • 使用加权概率和值查找数组中的项目

    上周我正在做的一个简单程序遇到了一些问题 这里有人帮助了我 现在我遇到了另一个问题 我目前有这个代码 var findItem function desiredItem var items item rusty nail probabili
  • Ajax - 下载前获取文件大小

    基本上 我想弄清楚是否应该使用 AJAX 下载文件 具体取决于文件大小有多大 我想这个问题也可以改写为 如何仅获取ajax请求的标头 EDIT ultima rat0 https stackoverflow com users 239962
  • Vue 3:“defineProps”引用本地声明的变量

    为什么我收到警告错误消息 defineProps引用本地声明的变量 eslint vue valid define props 当我在 props 中使用自定义验证器时SFC
  • escape()、encodeURI()、encodeURIComponent() 之间的区别

    在 JavaScript 中 它们之间有什么区别 escape unescape encodeuri decodeuri encodeURIComponent decodeURIComponent 对于有视觉头脑的人来说 这里有一个表格显示
  • window.print() 仅打印屏幕的“可视”部分

    我有一个可滚动屏幕 上面有一个打印按钮 并且在其 onclick 事件上调用 window print 函数 我的问题是它只打印屏幕的 可见 部分 而不是整个屏幕 如果页面可滚动 则当内容无法容纳在 1 页中时 打印应扩展到 2 或更多 页
  • Twitter-Typeahead 不提供建议

    我正在尝试使用twitter typeahead rails 我的目的是当我在 Typeahead 输入框中键入内容时 通过下拉框建议模型 User 的实例 但是 当我打字时什么也没有发生 有人看到我的代码有什么问题吗 Gemfile ge
  • 如何确定输入的模式是“Int,VarChar,Date,Time ...”等

    我有一个下拉菜单 其中包含DataType 和一个文本框 这是用于输入的Regex Pattern 如果我进入 test 在文本框中 或从下拉菜单中选择Int 如果在文本框中输入 则其模式是错误的 0 9 那么它的correct patte
  • 检测“文件下载”弹出窗口何时关闭

    我有一个网页 用 JSF 制作 其中一些链接允许用户获取 PDF 文件 当用户点击这样的链接时 会显示一个等待弹出窗口 它是一个模式面板 因为 PDF 的生成可能很长 并且一旦创建文件 IE 就会显示 文件下载 弹出窗口 建议 打开 保存
  • 使用 JS 或 Jquery 禁用浏览器窗口中的声音

    有没有办法禁用可能嵌入视频的浏览器窗口上的所有声音 我不是在寻找特定的解决方案 例如使用 js 等定位 Youtube 我需要一些通用的东西来关闭该页面的所有声音 这样如果任何视频播放它就没有声音 需要一些在页面级别关闭声音的东西 而不是通
  • 从字符串渲染 React 组件

    我在字符串中有一些 React 代码 例如 const component function App return div test div 我希望能够从浏览器内渲染该组件 例如 import React Component from re
  • JavaScript 使用多少位来表示数字?

    JavaScript 使用多少位来表示数字 一般JS实现使用64位双精度浮点数 对 32 位整数执行按位运算
  • 类型错误 [ERR_INVALID_ARG_TYPE]:“路径”参数必须是字符串类型。收到的类型未定义

    我正在尝试在本地计算机中运行反应应用程序 运行时出现此错误npm run start gt node scripts start js internal validators js 125 throw new ERR INVALID ARG
  • 无限滚动 jQuery 和 Laravel 5 分页

    我成功从控制器返回数据 public function index posts Post with status verified gt paginate 30 return view show gt with compact posts

随机推荐

  • Windows文本编辑器——推荐、介绍与安装(1)

    撰写时间 2023年4月11日 目的 介绍各种类型的文本编辑器 阐述编辑器的优缺点 并提供安装与使用方法 前言 文本编辑器是应用各种已有的编程语言进行软件开发的一种重要工具 它能够帮助开发者更加高效地编写代码 也能够帮助电脑小白快速上手各种
  • Qt Model View TreeView及对应Model

    点击上方蓝字可直接关注 方便下次阅读 如果对你有帮助 可以点个在看 让它可以帮助到更多老铁 一 概述 接着之前的话题继续 如果把之前的QTableView改成QTreeView 我们在不改变Model的情况下可以直接得到一个没有结构层次的
  • Linux KVM 使用教程(一)

    文章目录 1 KVM简介 2 KVM 的功能列表 3 KVM 工具集合 3 1 Virsh命令 1 KVM简介 1 KVM 全称是 基于内核的虚拟机 Kernel based Virtual Machine 它是Linux 的一个内核模块
  • python2(基本)

    实验02 基本 一 课内实验题 共10小题 100分 题型得分 100 描述 编写程序 从键盘输入两个整数 计算并输出这两个整数的和 平均值 最小值和最大值 平均值保留2位小数 输入 分行输入两个整数 输出 分行输出两个整数的和 平均值 最
  • JDK1.8 下载与安装

    JDK安装 JDK1 8下载 下载链接 https www oracle com java technologies javase javase jdk8 downloads html 根据操作系统版本下载 这里以win10 64位操作系统
  • 驱动程序里ioctl下switch问题

    今天在写步进电机驱动程序时 switch语句引出3个分支 case 0 case 1 case 2 case 0 什么都不做 case 1让步进电机正向转动 case 2让步进电机反向转动 但是测试时 case 2怎么也动不起来 后来把ca
  • PLSQL Developer的配置方法

    1 下载32位的版本instantclient basic nt 11 2 0 3 0 zip 因为PLSQLDev是32位的 没有64位的版本 这 个和操作系统无关 2 instantclient下载完后是一个压缩文件 不需要安装 配置一
  • 服务器系统如何清理,服务器清理内存怎么清理

    服务器清理内存怎么清理 内容精选 换一换 本节操作指导您完成Windows操作系统云服务器磁盘空间清理 弹性云服务器匀出一部分磁盘空间来充当内存使用 当内存耗尽时 云服务器可以使用虚拟内存来缓解内存的紧张 但当内存使用率已经非常高时 频繁的
  • 关于HTTP协议,一篇就够了

    HTTP简介 HTTP协议是Hyper Text Transfer Protocol 超文本传输协议 的缩写 是用于从万维网 WWW World Wide Web 服务器传输超文本到本地浏览器的传送协议 HTTP是一个基于TCP IP通信协
  • TCP 连接管理机制(一)——TCP三次握手详解 + 为什么要有三次握手

    TCP是面向连接的协议 在通信之前需要先建立连接 其本质就是打开一个socket文件 这个文件有自己的缓冲区 如果要发送数据 上层把数据拷贝到发送缓冲区 如果是接收数据 OS直接把来自网络的数据拷贝到接收缓冲区里 那么三次握手期间 Serv
  • youversion.com的圣经无法使用、无法连接、无法下载离线版本的解决方法

    最近 youversion com的圣经无法使用 无法连接 无法下载离线版本了 这是一部很好用的圣经软件 以前一直用着 后来ipad越狱重新安装的时候就不能连接了 后来无意间发现原来是这个网站被和谐了 至于GCD为什么这么做 以咱的智商尚不
  • 接口自动化测试须知

    一 做接口测试需要哪些技能 做接口测试 需要的技能 基本就是以下几点 业务流 了解系统及内部各个组件之间的业务逻辑交互 数据流 了解接口的I O input output 输入输出 协议 包括http协议 TCP IP协议族 http协议
  • CMD查杀端口的两种方式

    第一种 netstat ano windows r输入cmd并打开 输入netstat ano 记住对应的6052 输入杀掉端口 taskkill pid 6052 f 第二种 netstat aon findstr 8080 直接输入ne
  • Win10 + VS2017 + Ceres配置

    前言 Ceres是google出品的一款基于C 的开源非线性优化库 官方文档 Ceres官方文档地址 依赖库 Eigen 官网 glog github gflags github Ceres github 配置过程 1 Eigen Eige
  • Python3 爬虫 requests+BeautifulSoup4(BS4) 爬取小说网站数据

    刚学Python爬虫不久 迫不及待的找了一个网站练手 新笔趣阁 一个小说网站 前提准备 安装Python以及必要的模块 requests bs4 不了解requests和bs4的同学可以去官网看个大概之后再回来看教程 爬虫思路 刚开始写爬虫
  • GPT专业应用:快速生成职位描述(JD)

    正文共 814 字 阅读大约需要 3 分钟 人力资源必备技巧 您将在3分钟后获得以下超能力 快速生成职位描述 Beezy评级 B级 经过简单的寻找 大部分人能立刻掌握 主要节省时间 推荐人 Kim 编辑者 Linda 图片由 Lexica
  • 数据中台与传统大数据平台有什么区别?_光点科技

    一 数据中台 数据中台是聚合和治理跨域数据 将数据抽象封装成服务 提供给前台以业务价值的逻辑概念 数据中台是在平台概念上的升级 不再单纯的将功能进行大杂烩 理念上 中台有几个特点 第一 更强调数据集中存储 统一管理 提供标准化的服务 第二
  • 【毕业设计】基于springboot + vue微信小程序商城

    目录 前言 创新点 亮点 毕设目录 一 视频展示 二 系统介绍 三 项目地址 四 运行环境 五 设计模块 前台 后台 六 系统功能模块结构图 数据库设计 七 准备阶段 使用真实支付 使用模拟支付 八 使用说明 九 登录后台 十 后台页面展示
  • 前端常用工具库方法整理

    欢迎点击领取 前端面试题进阶指南 前端登顶之巅 最全面的前端知识点梳理总结 前言 在闲余的时间整理一份我们可能用到的前端工具库方法 依赖库 名称 cropperjs 图片裁剪 exif js lrz 图片旋转问题 html2canvas d
  • React性能优化(完整版)

    我的博客 http wangxince site my demo markdown React 性能优化 1 减少 render 次数 shouldComponentUpdate PureComponent shouldComponentU