React组件性能优化若干问题

news2024/12/23 16:08:58

react组件的性能优化的核心是减少渲染真实DOM节点的频率减少Virtual DOM比对的频率

  1. 组件卸载前执行清理操作

在组件中为window 注册的全局事件,以及定时器,在组件卸载前要清理掉。防止组件卸载后继续执行影响应用性能。

import React from 'react'
import { useEffect } from 'react'
import { observer } from 'mobx-react-lite'

function TestAdvance () {
  useEffect(() => {
    let timer = setInterval(() => {
      console.log('定时器被触发了')
    }, 1000)
    // 返回一个卸载时会被触发的函数来对timer进行清理
    return () => clearInterval(timer)
  }, [])
  return <div>Test</div>
}

export default observer(TestAdvance)
  1. 通过纯组件提升组件性能(类组件)

  • 什么是纯组件(PureComponent)

纯组件会对组件输入的数据进行浅层比较,如果当前输入数据和上次输入数据相同,组件不会重新渲染。

  • 什么是浅层比较

  • 比较引用数据类型在内存中的引用地址是否相同;

  • 比较基本数据类型的值是否相同。

  • 如何实现纯组件

  • 类组件集成 PureComponent 类

  • 函数组件使用 memo 方法

import React from 'react'

class App extends React.Component {
  constructor () {
    super()
    this.state = {
      person: { name: '张三', age: 20, job: 'waiter' }
    }
  }

  updateName () {
    setInterval(() => {
      this.setState({ person: { ...this.state.person, name: '张三' } })
    }, 3000)
  }

  componentDidMount () {
    console.log('componentDidMount')
    this.updateName()
  }

  render () {
    return (
      <div>
        <RegularComponent name={this.state.person.name} />
        <PureComponent name={this.state.person.name} />
      </div>
    )
  }
}

class RegularComponent extends React.Component {
  render () {
    console.log('RegularComponent')
    return <div>{this.props.name}</div>
  }
}

class PureComponent extends React.PureComponent {
  render () {
    console.log('PureComponent')
    return <div>{this.props.name}</div>
  }
}

export default App
  • 浅层比较和深度diff的性能对比,为什么需要先进行浅层比较,而不直接进行diff比较呢。

和进行diff 比较相比,浅层比较将消耗更少的性能。diff 操作会重新遍历整棵 Virtual DOM树,而浅层比较只操作当前组件的 state 和 props。

可以看到PureComponent 当状态值没有改变时是不会被重新渲染的。

  1. 通过shouldComponentUpdate生命周期函数提升组件性能

shouldComponentUpdate是类组件当中的一个生命周期函数,它允许我们在这个方法当中通过返回true 或者 false,来决定是否要重新渲染组件。

纯组件只能进行浅层比较,要进行深层比较的话,需要使用到shouldComponentUpdate,它用于编写自定义比较逻辑。

函数的第一个参数时nextProps, 第二个参数是nextState。

在内存中当中有两个对象,即使这两个对象的长得一摸一样,实际上它们有不同的引用地址,这个时候再怎么比较他们都不相同。

在我们的自定义逻辑中,如果返回true,则需要重新渲染组件;如果返回false,则不需要重现渲染组件了。

import React from 'react'

class App extends React.Component {
  constructor () {
    super()
    this.state = {
      person: { name: '张三', age: 20, job: 'waiter' }
    }
  }

  updateName () {
    setInterval(() => {
      this.setState({ person: { ...this.state.person, job: 'Writer' } })
    }, 3000)
  }

  componentDidMount () {
    console.log('componentDidMount')
    this.updateName()
  }

  /* shouldComponentUpdate (nextProps, nextState) {
    if (
      nextState.person.age !== this.state.person.age ||
      nextState.person.name !== this.state.person.name
    ) {
      return true
    } else {
      return false
    }
  } */

  render () {
    return (
      <div>
        <RegularComponent name={this.state.person.name} />
        <PureComponent name={this.state.person.name} />
      </div>
    )
  }
}

class RegularComponent extends React.Component {
  render () {
    console.log('RegularComponent')
    return <div>{this.props.name}</div>
  }
  shouldComponentUpdate (nextProps, nextState) {
    console.log(this.props, nextProps)
    if (nextProps.name !== this.props.name) {
      return true
    } else {
      return false
    }
  }
}

class PureComponent extends React.PureComponent {
  render () {
    console.log('PureComponent')
    return <div>{this.props.name}</div>
  }
}

export default App
  1. 函数组件使用memo 减少渲染次数

4.1 memo的基本使用:

将函数组件变为纯组件,将当前props和上一次的props进行浅层比较,如果相同就阻止组件重新渲染。

// 未使用memo方法包裹组件
import React, { useEffect, useState } from 'react'

function App () {
  const [name] = useState('张三')
  const [index, setIndex] = useState(0)

  useEffect(() => {
    let timer = setInterval(() => {
      setIndex(prev => prev + 1)
    }, 1000)
    return () => {
      clearInterval(timer)
    }
  }, [index])
  return (
    <div>
      {index}
      <ShowName name={name} />
    </div>
  )
}

function ShowName ({ name }) {
  console.log('render...')
  return <div>{name}</div>
}

export default App

使用memo封装子组件,让子组件减少不必要的渲染。

// 使用memo封装子组件
import React, { memo, useEffect, useState } from 'react'
function App () {
  const [name] = useState('张三')
  const [index, setIndex] = useState(0)

  useEffect(() => {
    let timer = setInterval(() => {
      setIndex(prev => prev + 1)
    }, 1000)
    return () => {
      clearInterval(timer)
    }
  }, [index])
  return (
    <div>
      {index}
      <ShowName name={name} />
    </div>
  )
}

const ShowName = memo(function ({ name }) {
  console.log('render...')
  return <div>{name}</div>
})

export default App

可以看到仅初次渲染时,渲染了一次。

4.2 为memo 方法传递自定义比较逻辑

在memo方法内部,其实也是进行的浅层比较。这个浅层比较对于引用数据类型来说,比较的是数据的引用地址。所以如果遇到引用数据类型的话,我们需要去传递自定义比较逻辑。

memo方法是可以接收第二个参数的,第二个参数是一个函数,我们可以通过这个函数参数来编写我们自定义比较逻辑。该函数参数接收两个参数,分别是prevProps和nextProps。

与shouldComponentUpdate的返回值逻辑相反,返回true,则不重新渲染;返回false的话则需要重新渲染。如果想让这个组件重新渲染的话就返回false,否则返回true。

// 给memo传递第二个参数,自定义比较逻辑
import React, { memo, useEffect, useState } from 'react'

function App () {
  const [person, setPerson] = useState({ name: '张三', age: 20, job: 'waiter' })
  const [index, setIndex] = useState(0)

  useEffect(() => {
    let timer = setInterval(() => {
      setIndex(prev => prev + 1)
      setPerson({ ...person, job: 'chef' })
    }, 1000)
    return () => {
      clearInterval(timer)
    }
  }, [index, person])
  return (
    <div>
      {index}
      <ShowName person={person} />
    </div>
  )
}
function compare (prevProps, nextProps) {
  if (
    prevProps.person.name !== nextProps.person.name ||
    prevProps.person.age !== nextProps.person.age
  ) {
    return false
  }
  return true
}
const ShowName = memo(function ({ person }) {
  console.log('render...')
  return (
    <div>
      {person.name} {person.age}
    </div>
  )
}, compare)

export default App

5. 通过组件懒加载提供应用性能

使用组件懒加载,可以减少bundle 文件大小,加快组件呈递速度。

5.1 路由组件懒加载

import React, { lazy, Suspense } from 'react'
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom'
// import Home from './pages/Home'
// import List from './pages/List'
// import NotFound from './pages/NotFound'

const Home = lazy(() => import(/* webpackChunkName: "Home" */ './pages/Home'))
const List = lazy(() => import(/* webpackChunkName: "List" */ './pages/List'))
const NotFound = lazy(() => import('./pages/NotFound'))

function App () {
  return (
    <BrowserRouter>
      <Link to='/'>首页 </Link>
      <Link to='/list'>列表页</Link>
      <Suspense fallback={<div>loading...</div>}>
        <Routes>
          <Route path='/' element={<Home />} />
          <Route path='/list' element={<List />} errorElement={<NotFound />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  )
}

export default App

可以看到,List页面chunk 只有在页面被加载渲染时才被被请求下载。

5.2 根据条件进行组件懒加载

适用于组件不会随条件频繁切换。

import React, { lazy } from 'react'
import { Suspense } from 'react'

function Test () {
  let LazyComponent = null
  if (false) {
    LazyComponent = lazy(() =>
      import(/* webpackChunkName: "Home-Test" */ './Home')
    )
  } else {
    LazyComponent = lazy(() =>
      import(/* webpackChunkName: "List-Test" */ './List')
    )
  }
  return (
    <Suspense fallback={<div>Test loading...</div>}>
      <LazyComponent />
    </Suspense>
  )
}

export default Test

6. 通过使用占位符标记提升React组件的渲染性能

6.1 使用Fragment 避免额外标记

React组件中返回的jsx 如果有多个同级元素,多个同级元素必须要有一个共同的父级。

<div>
...
</div> 
// 上面会多出一个无意义标记

// 应该改为 
<fragment>
...
</fragment>
// 或者写成下面这样也是可以的
<>
...
</>

为了满足上面的条件,我们通常都会在最外层添加一个div,但是这样的话就会多出一个无意义的标记。如果每个组件都多出这样的一个无意义标记的话,浏览器渲染引擎的负担就会加剧。

为了解决这个问题,react推出了fragment占位符标记。使用占位符标记,既满足了拥有共同的父级的要求,又不会多出额外的无意义标记。

另外,fragment标记对也可以简写成 :<></>

7. 通过避免使用内联函数提升组件性能

因为在使用内联函数后,render 方法每次进行时都会创建该函数的新实例,导致 React 在进行Virtual DOM比对时,新旧函数比对不相等,导致总是为元素绑定新的函数实例,而旧的函数实例又要交给垃圾回收器处理。

正确的做法是:在组件中单独定义函数,将函数绑定给事件。

render(){return(<input onChange={e => this.setState({inputValue: e.target.value})} />)}
// 在类组件中,应该采用下面的方式来改写从而避免该元素被重新渲染
setInputvalue = e => {
    this.setState({inputValue: e.target.value})
}
render(){
    return (<input onChange={this.setInputValue} />)
}

这样一来,无论render方法被重新执行多少次,类的属性是不会发生变化的,所以在这个地方即使render方法被重新执行n次,那它每次都不会产生新的函数实例,所以它每次不会给onChange去添加新的函数。

8. 在构造函数中进行this指向的更正

在类组件中如果使用fn(){}这种方式定义函数,函数this默认指向 undefined 。也就是说函数内部的 this 指向需要被更正。

可以在构造函数中对函数的this 进行更正,也可以在行内进行更正。两者看起来没有太大的区别,但是对性能的影响是不同的。

对于行内更正来说,每一次render方法在执行的时候它都会调用bind方法生成新的函数实例,也就是上边提到的内联函数对性能的影响是一样的。

因此比较推荐的是在构造函数当中去更正this的指向。因为构造函数只执行一次,也就是函数的this 指向只更正一次,效率较高。

import React, { Component } from 'react'

export default class index extends Component {
  constructor () {
    super()
    // 方法一:(推荐使用)
    // 构造函数只执行一次,所以函数this 指向更正的代码也只执行一次。
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick () {
    console.log(this)
  }
  handleClick2= () {
    console.log(this)
  }
  render () {
    // 方式二:跟内联函数类似,不推荐,应避免使用
    // 问题:render 放啊每次执行时都会调用bind方法生成新的函数实例。
    return <button onClick={this.handleClick.bind(this)}>按钮</button>
  }
}

9. 类组件中的箭头函数

在类组件中使用箭头函数不会存在this 指向问题。因为箭头函数本身并不绑定this.

handleClick2= ()=> console.log(this)

箭头函数在this 指向问题上是比较占优势的,但是同时也有不利的一面。

当使用箭头函数时,该函数被添加为类的实例对象属性,而不是原型对象属性。如果组件被多次重用,每个组件实例对象中都会有一个相同的函数实例,降低了函数实例的可重用性,造成了资源浪费。

综上所述, 更正函数内部this 指向的最佳做法是: 在构造函数中使用 bind 方法进行绑定。

10. 避免使用内联样式属性以提升组件性能

当使用内联style 为元素添加样式时,内联style 会被编译成 JavaScript 代码,通过JavaScript代码将样式规则映射到元素的身上,浏览器就会花费更多的时间执行脚本和渲染UI,从而增加了组件的渲染时间。

// 例如:这段代码的样式会涉及到脚本的执行,效率低,资源开销大
<div style={{background: 'red'}}>Style in line</div>

更好的办法是:

将CSS 文件导入样式组件,能通过CSS直接做的事情就不要通过JavaScript去做。因为JavaScript操作DOM非常慢。而CSS默认开启了GPU的渲染加速,更加高效。

11. 优化条件渲染以提升组件性能

频繁的挂载和卸载组件,是一项耗性能的操作。为了确保应用程序的性能,应该减少组件挂载和卸载的次数。

在react中,我们经常会根据条件渲染不同的组件,条件渲染是一项必做的优化操作。

import React from 'react'
import Home from './Home'
import List from './List'
import Test from './Test'

function App () {
  if (true) {
    return (
      <>
        <Test />
        <Home />
        <List />
      </>
    )
  } else {
    return (
      <>
        <Home />
        <List />
      </>
    )
  }
}

export default App

在上面的代码中,显然这种大范围的条件渲染不太合理,存在优化的空间,整个页面随着判断条件改变而变化的部分只有Test 组件,因此,可以仅对Test组件进行条件渲染判断,从而减少不必要的组件卸载和挂载的次数。

import React from 'react'
import Home from './Home'
import List from './List'
import Test from './Test'

function App () {
  return (
    <>
      {true && <Test />}
      <Home />
      <List />
    </>
  )
}

export default App

12. 避免重复的无限渲染

当应用程序状态发生更改时,react 就会调用render 方法,如果在render 方法中继续更改应用程序状态,就会发生render 方法递归调用导致应用报错。

import React, { Component } from 'react'

export default class index extends Component {
  constructor () {
    super()
    this.state = { name: '张三' }
    // 方法一:(推荐使用)
    // 构造函数只执行一次,所以函数this 指向更正的代码也只执行一次。
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick () {
    console.log(this)
  }
  render () {
    this.setState({ name: '李四' })
    // 方式二:跟内联函数类似,不推荐,应避免使用
    // 问题:render 放啊每次执行时都会调用bind方法生成新的函数实例。
    return <button onClick={this.handleClick.bind(this)}>按钮</button>
  }
}

与其他生命周期函数不同,render方法应该被作为纯函数。

这意味着,在render方法中不要做以下的事情:

  • 不要调用setState方法;

  • 不要使用其他手段查询更改原生DOM元素;

  • 以及不要做其他更改应用程序的任何操作。

render 方法对的执行要根据状态的改变,这样可以保持组件的行为和渲染方式一致。

所以,在react当中,不要在render方法当中,不要在componentWillUpdate这个生命周期函数当中,不要在componentDidUpdated这个生命周期函数当中继续调用setState方法去更新状态。否则将导致重复的无限渲染,应用程序崩溃。

13. 为应用程序创建错误边界

默认情况下,组件渲染错误会导致整个应用程序的中断,创建错误边界可确保在特定组件发生错误时应用程序不会中断。从而增加应用程序的健壮性(鲁棒性)。

错误边界是一个React组件,可以捕获子级组件在渲染时发生的错误,当错误发生时,可以将错误记录下来,可以显示备用UI界面。

错误边界涉及两个生命周期函数,分别为:getDerivedStateFromError 和 componentDidCatch.

getDerivedStateFromError: 是一个静态方法,方法中返回一个对象,该对象会和state 对象进行合并,用于更改应用程序的状态,从而给我们提供显示备用UI界面的机会。

componentDidCatch:该方法用于记录应用程序的错误信息,该方法的参数就是错误对象。

import React, { Component } from 'react'
import ErrorTrigger from '../components/ErrorTrigger'

export default class ErrorBoundaries extends Component {
  constructor () {
    super()
    this.state = {
      hasError: false
    }
  }
  componentDidCatch (error) {
    // 可以将程序错误信息记录到远端服务器
    console.log('componentDidCatch')
  }
  static getDerivedStateFromError () {
    console.log('getDerivedStateFromError')
    return {
      // 该返回对象会和state 对象进行合并
      hasError: true
    }
  }
  render () {
    if (this.state.hasError) {
      return <>我是备用UI界面</>
    }
    return (
      <>
        <ErrorTrigger />
      </>
    )
  }
}
import React, { Component } from 'react'

export class ErrorTrigger extends Component {
  render () {
    throw new Error('错误边界内发生错误了')
    return <div>ErrorTrigger</div>
  }
}

export default ErrorTrigger

注意⚠️:错误边界不能捕获异步错误,例如点击按钮时发生的错误。

14. 避免数据结构突变

组件中的props和state 的数据结构应该保持一致,数据结构突变会导致输出不一致。

import React, { Component } from 'react'

export default class App extends Component {
  constructor () {
    super()
    this.state = {
      person: {
        name: '张三',
        age: 20,
        job: 'waiter'
      }
    }
  }
  render () {
    const { name, age, job } = this.state.person
    return (
      <>
        <p>
          {name} {age} {job}
        </p>
        <button
          onClick={() =>
            this.setState({
              ...this.state,
              person: {
                age: 30
              }
            })
          }
        >
          更新信息
        </button>
      </>
    )
  }
}

点击更新信息按钮前

点击更新信息按钮后

这是因为数据状态在发生更改时,发生了数据结构突变导致的数据丢失

使用setState更改状态代码应该修改为:

this.setState({
  ...this.state,
  // 这里的person 数据结构应该和原来的保持一致,避免数据丢失
  // person: {
  //   age: 30
  // }
  person: {
    ...this.state.person,
    age: 30
  }
})

修改更新数据保持结构一致的代码后点击更新信息按钮后的显示

15. 优化依赖项大小

在程序应用开发中,常常会依赖第三方包,但我们不想引用包中所有的代码,我们只想用到哪些代码就包含哪些代码

此时,可以使用插件对依赖项进行优化,优化资源。

拿lodash举例:

应用基于create-react-app 脚手架创建:

  1. 下载依赖,
npm install react-app-rewired customize-cra lodash babel-plugin-lodash

react-app-rewired: 覆盖create-react-app的默认配置

module.exports = function(oldConfig){
  return newConfig
}
// 参数中的oldConfig 就是默认的webpack config

customize-cra: 导出了一些辅助方法,可以让以上写法更加简洁。

const {override, useBabelRc} from 'customize-cra'

module.exports = override(
(oldConfig) => newConfig,
(oldConfig) => newConfig
)

// override 可以接收多个参数,每个参数都是一个配置函数,函数接收oldConfig,返回 newConfig
// useBabelRc 允许使用 .babelrc 文件进行 babel 配置

babel-plugin-lodash: 对应用中的lodash 进行精简

  1. 在项目根目录下新建 config-overrides.js 并加入配置代码
const {override, useBabelRc} from 'customize-cra'
module.exports = override(useBabelRc())
// 这里使用 .babelrc 文件进行 babel 配置
  1. 修改package.json 中的文件构建命令

把原来命令中的 react-scripts 改为 react-app-rewired

  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject" 
  },
  1. 创建 .babelrc 文件并加入配置
{
    "plugins":["lodash"]
}
  1. 命令打包生成的生产环境下的三种js文件
  1. main.[hash].chunk.js 主应用程序代码,App.js 等

  1. 1.[hash].chunk.js 第三方依赖包的代码,包含在node_modules中导入的模块

  1. runtime~main.[hash].js webpack的运行时代码

  1. 优化前后结果比对:

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

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

相关文章

分享十个前端Web3D可视化框架附地址

Three.js&#xff1a;Three.js是一个流行的3D库&#xff0c;提供了大量的3D功能&#xff0c;包括基本几何形状、材质、灯光、动画、特效等。它是一个功能强大、易于使用的框架&#xff0c;广泛用于Web3D可视化应用程序的开发。Three.js&#xff1a;https://threejs.org/Babylon…

【强烈建议收藏:MySQL面试必问系列之索引专题】

一.知识回顾 前面的文章我们一起学习了数据库的事务、事务以及并发来的问题、数据库锁机制、数据库中CURD的SQL语句底层执行流程、数据库SQL优化专题&#xff0c;如果你一步一步的跟下来&#xff0c;一定会帮助你建立一个知识体系。接下来我们再一起学习数据库索引专题&#x…

Toponogov 比较定理及其应用

1. Toponogov 比较定理的背景来源 Victor Andreevich Toponogov&#xff08;1930-2004&#xff09; 是苏联数学家&#xff0c;Toponogov 比较定理是他的博士论文题目&#xff0c;在1958年答辩。他证明这个定理是为了用于证明截面曲率假设下的分裂定理和最大直径定理&#xff0…

具有精密内部基准的 DACx0502 简介及驱动应用示例

DACx0502 说明 16 位 DAC80502、14 位 DAC70502 和 12 位DAC60502 (DACx0502) 数模转换器 (DAC) 均为具有电压输出的高精度、低功耗器件。 DACx0502 线性度小于 1LSB。凭借高精度和微型封装特性&#xff0c;DACx0502 非常适合以下 应用&#xff1a; 增益和失调电压校准、电流…

计算机网络协议详解(二)

文章目录&#x1f525;HTTP协议介绍&#x1f525;HTTP协议特点&#x1f525;HTTP协议发展和版本&#x1f525;HTTP协议中URI、URL、URN&#x1f525;HTTP协议的请求分析&#x1f525;HTTP协议的响应分析&#x1f525;MIME类型&#x1f525;HTTP协议介绍 HTTP协议介绍 什么是超…

反转链表(精美图示详解哦)

全文目录引言反转链表题目描述与思路实现总结引言 在学习了单链表的相关知识后&#xff0c;尝试实现一些题目可以帮助我们更好的理解单链表的结构以及对其的使用。 从这篇文章开始&#xff0c;将会介绍一些编程题来帮助我们更好的掌握单链表&#xff1a; 分别是反转链表、链表…

大数据技术之Hadoop集群配置

作者简介&#xff1a;大家好我是小唐同学(๑>؂<๑&#xff09;&#xff0c;好久不见&#xff0c;为梦想而努力的小唐又回来了&#xff0c;让我们一起加油&#xff01;&#xff01;&#xff01; 个人主页&#xff1a;小唐同学(๑>؂<๑&#xff09;的博客主页 目前…

SpringBoot三种方法实现定时发送邮件的案例

前言 小编我将用CSDN记录软件开发之路上所学的心得与知识&#xff0c;有兴趣的小伙伴可以关注一下&#xff01;也许一个人独行&#xff0c;可以走的很快&#xff0c;但是一群人结伴而行&#xff0c;才能走的更远&#xff01;让我们在成长的道路上互相学习&#xff0c;让我们共…

了解java

#常见编程语言介绍 C语言 C语言 java语言 javaScript语言 PHP语言 python语言Object-C和Swift语言 C# &#xff08;c sharp&#xff09;语言 Kotlin语言 Go语言 Basic语言 #JAVA的发展 起源于1991年SUN公司GREEN项目&#xff0c;1996年JDK1.0正式发布 后被Oracle公司收购&…

卷积神经网络CNN之ZF Net网络模型详解(理论篇)

1.背景 2. ZF Net模型结构 3. 改进优缺点 一、背景 ZF Net是用作者的名字命名的&#xff0c;Matthew D.Zeiler 和 Rob Fergus &#xff08;纽约大学&#xff09;&#xff0c;2013年撰写的论文&#xff1b; 论文原网址https://arxiv.org/abs/1311.2901 论文名&#xff1a;Vis…

Vue2的基本内容(一)

目录 一、插值语法 二、数据绑定 1.单向数据绑定 2.双向数据绑定 三、事件处理 1.绑定监听 2.事件修饰符 四、计算属性computed和监视属性watch 1.计算属性-computed 2.监视属性-watch &#xff08;1&#xff09;通过 watch 监听 msg 数据的变化 &#xff08;2&a…

IronXL for .NET 2023.2.5 Crack

关于适用于 .NET 的 IronXL 在 C# 中阅读和编辑 Excel 电子表格&#xff0c;无需 MS Office 或 Excel Interop。 IronXL for .NET 允许开发人员在 .NET 应用程序和网站中读取、生成和编辑 Excel&#xff08;和其他电子表格文件&#xff09;。您可以读取和编辑 XLS/XLSX/CSV/TS…

Apollo控制部分1-- ControlComponent组件介绍

Apollo控制部分1-- ControlComponent组件介绍摘要一、ControlComponent1、启动文件解析2、ControlComponent()组件函数解析1&#xff09;ControlComponent::ControlComponent() 构造函数2&#xff09;ControlComponent::Init() 初始化函数&#xff08;执行一次&#xff09;3&am…

分享四个前端Web3D动画库在Threejs中使用的动画库以及优缺点附地址

Threejs中可以使用以下几种动画库&#xff1a;Tween.js&#xff1a;Tween.js是一个简单的缓动库&#xff0c;可以用于在three.js中创建简单的动画效果。它可以控制数值、颜色、矢量等数据类型&#xff0c;并提供了多种缓动函数&#xff0c;例如线性、弹簧、强化、缓冲等等。区别…

Linux性能学习(2.3):内存_为什么分配的内存比申请的内存大16个字节

文章目录1 验证申请不同内存&#xff0c;系统分配机制1.1 代码1.2 测试1.3 结论2 为什么会多分配内存3 为什么会有4字节不可使用参考资料&#xff1a;https://www.gnu.org/software/libc/ 在上一篇文章中&#xff0c;探讨了Linux系统对进程以及线程的内存分配问题&#xff0c;…

流程图简介

一、流程与流程图1. 什么是流程具体来说&#xff0c;流程是一项活动或一系列连续有规律的事项或行为进行的程序。流程有6个要素&#xff0c;分别是&#xff1a;资源、过程、结构、结果、对象和价值。一个流程会把这些基本要素串联起来&#xff0c;例如流程中资源的输入、流程中…

gprof2dot perf

什么是gprof2dot 这是一个用于将许多探查器的输出转换为点图Python脚本。 使用需要安装的依赖 Python: known to work with version 2.7 and 3.3; it will most likely not work with earlier releases.Graphviz: tested with version 2.26.3, but should work fine with ot…

【C++】类和对象补充知识点

&#x1f3d6;️作者&#xff1a;malloc不出对象 ⛺专栏&#xff1a;C的学习之路 &#x1f466;个人简介&#xff1a;一名双非本科院校大二在读的科班编程菜鸟&#xff0c;努力编程只为赶上各位大佬的步伐&#x1f648;&#x1f648; 目录前言一、再谈构造函数1.1 构造函数体赋…

逻辑电路代数运算(上)

逻辑代数L是一个封闭的代数系统&#xff0c;由一个逻辑变量集K&#xff0c;常量0和1&#xff0c;以及与或非三种基本运算构成。 参与逻辑运算的变量叫逻辑变量&#xff0c;用字母A&#xff0c;B……表示。每个变量的取值非0 即1。 0、1不表示数的大小&#xff0c;而是代表两种不…

三天吃透Java基础八股文

本文已经收录到Github仓库&#xff0c;该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点&#xff0c;欢迎star~ Github地址&#xff1a;https://github.com/…