大厂进阶四:React源码Fiber架构解析
本文主要内容:
1、React Concurrent
2、React15架构
3、React16架构
4、Fiber架构
5、任务调度循环和fiber构造循环区别
一、React Concurrent
React在解决CPU卡顿是会用到React Concurrent
的概念,它是React中的一个重要特性和模块,主要的特点和原理如下
一、主要特点和优势
1、时间切片(Time Slicing)
允许将长时间运行的任务分割成小块,在不阻塞主线程的情况下逐步执行。例如,在一个复杂的数据计算或渲染大型组件树时,React可以将这些任务分成多个小片段,在每一帧的空闲时间里执行一部分,这样就不会导致页面出现卡顿,保证了页面的响应性。
对于用户体验来说至关重要,用户在操作过程中不会感觉到界面被冻结,仍然可以进行其他交互,比如滚动页面、点击按钮等。
2、 并发渲染(Concurrent Rendering)
React可以同时处理多个渲染任务,根据任务的优先级和紧急程度来合理安排渲染顺序。
对于有紧急更新(如用户交互导致的状态变化)和非紧急更新(如后台数据的缓慢加载更新)的场景非常有用。紧急更新会被优先处理,以确保用户操作能够立即得到反馈,非紧急更新则在合适的时机进行,避免影响性能。
3、Suspense 组件和懒加载(Lazy Loading)
Suspense
组件用于在等待异步数据加载时显示一个加载状态或者回退内容。比如,当一个页面依赖于从服务器获取的数据来渲染组件时,在数据加载过程中可以显示一个加载动画,提升用户体验。
懒加载允许在真正需要的时候才加载组件或模块。例如,对于一个大型应用,某些页面或功能模块可能不是在初始加载时就需要的,通过懒加载可以减少初始加载时间,提高应用的启动速度。当用户导航到相应的页面或触发特定功能时,对应的组件或模块才会被加载。
二、工作原理
1、 任务调度
React
内部有一个任务调度器,它负责管理和分配任务的执行时间。调度器会根据浏览器的每一帧的时间预算,将任务分割成合适的时间片来执行。
对于不同优先级的任务,调度器会采用不同的策略。高优先级的任务(如用户交互响应)会尽快得到执行,而低优先级的任务(如数据预取)则会在系统空闲时执行。
2、纤维架构(Fiber Architecture)
的支持
React
的纤维架构是实现并发功能的基础。纤维是一种轻量级的数据结构,每个纤维代表一个组件。在渲染过程中,React
可以暂停、恢复和重新调度纤维的渲染。
纤维架构使得React
能够在渲染过程中进行中断和恢复,以便在合适的时机处理其他任务。例如,当一个组件的渲染被中断时,React
会保存当前的渲染状态,然后在后续合适的时间点继续渲染。
二、React15架构
在 React 15 架构中:
1、 Reconciler(协调器)负责找出变化的组件
reconciler(协调器)采用的是 stack reconciler
解决方案。它在更新子组件时会进行递归
操作,且一旦开始更新就无法中断。当组件层级较深时,这种同步的递归更新可能会导致在一帧内无法完成更新,从而使用户交互出现卡顿的情况。为了解决卡顿16版本进行了功能重构。
(一)工作方式
在React
中可以通过this.setState、 this.forceUpdate、ReactDom.render
等API触发更新。
每当有更新发生时,reconciler
会做如下工作:
触发更新。
- 调用函数组件、或class组件的
render
方法,将返回的JSX
转化为虚拟DOM
- 将
虚拟DOM
和上次更新时的虚拟DOM
对比 - 通过对比找出本次更新中变化的
虚拟DOM
- 通知
Renderer
将变化的虚拟DOM
渲染到⻚面上
在 React 15 版本中,Reconciler(协调器)
的工作方式具有以下特点和原理:
(二)功能
1、 构建虚拟 DOM 树
React 维护了一个虚拟 DOM(Virtual DOM)的概念。在 React 15 中,Reconciler 负责根据组件的定义和状态构建虚拟 DOM 树。每个 React 组件都对应虚拟 DOM 树中的一个节点,包含组件的类型、属性、子节点等信息。
例如,当定义一个简单的 <div>
组件时,Reconciler 会为其创建相应的虚拟 DOM 节点来表示这个组件在虚拟 DOM 树中的结构和属性。
2、 协调更新
当组件的状态或属性发生变化时,Reconciler 会启动更新流程。它会比较变化前后的虚拟 DOM 树,以确定哪些部分需要进行实际的 DOM 操作来更新页面。
例如,当一个按钮组件的文本从“点击我”变为“已点击”时,Reconciler 会识别出这个变化,并确定需要更新对应的 DOM 元素中的文本内容。
3、 管理组件生命周期
Reconciler 在协调过程中还会触发组件的生命周期方法。在 React 15 中,常见的生命周期方法如 componentWillMount
、componentDidMount
、componentWillReceiveProps
、shouldComponentUpdate
、componentWillUpdate
、componentDidUpdate
等。
比如在组件挂载阶段,componentWillMount
和 componentDidMount
会依次被调用,让开发者可以在这些方法中执行一些初始化操作或发送网络请求等。
(三)原理
1、深度优先遍历和递归
Reconciler 采用深度优先遍历
的方式来递归地处理虚拟 DOM 树。从根节点开始,依次遍历每个子节点及其子树。
例如,对于如下的组件结构:<Parent><Child1><GrandChild1></GrandChild1></Child1><Child2></Child2></Parent>
,它会先处理 Parent
组件,然后是 Child1
,接着是 GrandChild1
,再回到 Child2
。
在递归过程中,每个组件会根据自身的 render
方法生成新的虚拟 DOM 子树,然后 Reconciler
继续对这些子树进行处理。
2、 diff 算法比较
在更新阶段,Reconciler
使用 diff 算法来比较新旧虚拟 DOM 树的差异。它会逐个节点地进行比较,检查节点类型、属性、子节点等方面的变化。
如果节点类型不同,React 通常会认为整个子树都发生了变化,会销毁旧的 DOM 节点并创建新的 DOM 节点。例如,旧的虚拟 DOM 节点是 <div>
,新的是 <span>
,那么整个 <div>
及其内部的子节点都会被替换为 <span>
及其子节点。
如果节点类型相同,会进一步比较属性的变化。例如,检查 className
、style
等属性是否有更新,如果有变化,就会相应地更新实际的 DOM 元素的属性。
对于子节点,会通过遍历和比较的方式来确定子节点的添加、删除或移动等操作。
2、Renderer(渲染器)负责将变化的组件渲染到页面上
(一) 同步更新
React 15 的 Reconciler 执行更新是同步
的。这意味着当一个 setState 触发更新时,React 会立即开始进行 Reconciliation(协调)
和 Rendering(渲染)
过程,直到整个更新过程完成。
虽然同步更新在一些简单场景下比较直观,但在复杂的应用中,如果有大量的计算或长时间的同步操作,可能会导致页面卡顿
,因为浏览器在更新过程中无法响应用户交互或进行其他任务。
(二)更新原理图
图中state.count乘以2
之后,Reconciler
找出变化的组件交给renderer
进行更新,整个过程是同步递归实现
的,直到组件都遍历完成。
在 React 16 及以后的版本中,Reconciler 进行了重大的改进,引入了 Fiber 架构,使得更新过程可以被中断和恢复,提高了性能和用户体验。
三、React16架构
1、 Scheduler(调度器)
调度任务的优先级,高优任务进入Reconciler
React Scheduler
的优先级划分主要基于以下几个方面:
一、不同优先级的分类
-
Immediate Priority
(同步优先级)
这是最高优先级,通常用于处理用户交互等关键操作,比如处理点击事件、键盘输入等。这些操作需要立即得到响应,以提供流畅的用户体验。当任务具有同步优先级时,React 会尽可能快地执行它,甚至可能中断正在进行的其他任务来处理它。
-
UserBlocking Priority
(用户阻塞优先级)
此优先级用于那些会影响用户体验,但不是立即关键的任务。例如,一些数据预取操作,虽然不是立即必需,但如果延迟太久会让用户感觉到卡顿。通常会在不影响当前用户交互的情况下尽快执行。
-
Normal Priority
(普通优先级)
这是默认的优先级级别,适用于大多数常规的更新和渲染任务。比如组件的状态更新导致的重新渲染通常是普通优先级。React 会在合适的时机调度和执行这些任务,以平衡性能和响应性。
-
Low Priority
(低优先级)
用于不太紧急的任务,比如一些后台数据同步或者非关键的日志记录等。这些任务可能会在其他更高优先级的任务完成后,或者在系统空闲时才会被执行。
-
Idle Priority
(空闲优先级)
这是最低的优先级,用于那些可以在任何时间执行,并且不会影响用户体验的任务,比如一些清理操作或者统计信息的收集等。
通常在浏览器空闲时间执行,不会抢占其他任务的执行时间。
2、 Reconciler(协调器)
负责找出变化的组件
React16的Reconciler更新机制发生了变化
在版本15中是递归方式
在版本16中是可以中断的循环过程
function performSyncWorkOnRoot(root) {// 开始同步更新根节点const finishedWork = workLoopSync();// 完成更新后进行提交阶段commitRoot(root, finishedWork);
}function workLoopSync() {while (workInProgress!== null && !shouldYield()) {performUnitOfWork(workInProgress);}return workInProgress;
}function performUnitOfWork(fiber) {const next = beginWork(fiber);if (next === null) {completeUnitOfWork(fiber);} else {workInProgress = next;}
}
workLoopSync
是一个同步工作循环函数。它的主要目的是在同步模式下处理工作单元(可能是 React 组件的更新任务)。
循环条件包含两个部分:
workInProgress!== null
:只要还有未完成的工作(workInProgress
不为空),循环就会继续。workInProgress
通常代表当前正在处理的 Fiber 节点。!shouldYield()
:在每一次循环迭代中,会检查是否应该让出执行权(yield
)。如果shouldYield()
返回false
,表示可以继续执行当前的工作,不会中断循环;如果返回true
,则表示可能需要暂停当前工作,给其他任务或浏览器一些时间来处理其他事情(例如响应用户输入、渲染动画等)。
例如:在处理一个大型组件树时,如果浏览器的每一帧时间内还有剩余时间来处理更多的更新工作,workLoopSync
会继续处理下一个工作单元;如果当前帧的时间已经用尽,shouldYield()
可能会返回true
,导致循环暂停,等待下一个机会继续执行。
3、Renderer(渲染器)
负责将变化的组件渲染到页面上
在React16中的变化:
Reconciler
与Renderer
不再是交替工作。当Scheduler
将任务交给Reconciler
后,Reconciler
会为变化的虚拟DOM打上代表增/删/更新的标记
整个Scheduler
与Reconciler
的工作都在内存中进行。只有当所有组件都完成
Reconciler的工作,才会统一交给
Renderer。
其中红框中的步骤随时可能由于以下原因被中断:
- 有其他更高优任务需要先更新
- 当前帧没有剩余时间
由于红框中的工作都在内存中进行,不会更新页面上的DOM,所以即使反复中断,用户也不会看见更新不完全的DOM
四、Fiber架构
以下是关于 React Fiber 的详细介绍:
1、React Fiber 定义
React Fiber 是 React 16 对其核心算法(Reconciler,协调器)进行的一次重写,它是一种新的协调算法和架构模式。目的是使 React 能够更好地处理大型应用程序和更复杂的更新,同时提高应用的响应性和用户体验。
特点:支持状态更新、优先级调度、异步可中断
1. 作为架构来说
之前React15
的Reconciler采用递归的方式执行,数据保存在递归调用栈中,所以被称为stack Reconciler
。React16
的Reconciler基于Fiber节点实现,被称为Fiber Reconciler
;
2. 作为静态的数据结构来说
每个Fiber节点对应一个React element
,保存了该组件的类型(函数组件/类组件/原生组件…)、对应的DOM节点等信息;
3. 作为动态的工作单元来说
每个Fiber节点保存了本次更新中该组件改变的状态、要执行的工作(需要被删除/被插入页面中/被更新…);
2、原理解析
-
任务分割与优先级处理
React Fiber 将更新任务分割成一个个小的工作单元(Fiber 节点)。每个 Fiber 节点代表一个组件或者 DOM 节点的更新任务。引入了优先级的概念,不同的更新任务可以有不同的优先级。高优先级的任务(如用户交互产生的更新)可以中断低优先级的任务(如数据预取后引发的更新),优先得到处理。
-
可中断与恢复
在执行更新任务时,React Fiber 采用了可中断的循环方式。通过requestIdleCallback
(在不支持的浏览器中使用setTimeout
模拟)等机制,React 可以在每一个时间片(大约 5ms)内执行一部分任务。如果在一个时间片内没有完成当前任务,它会保存当前的状态,让出主线程的控制权,等待下一个时间片继续执行,从而实现可中断与恢复。
-
Fiber 节点结构
Fiber 节点包含了多个重要的属性:return
:指向父节点,用于在遍历树时回溯。child
:指向第一个子节点。sibling
:指向下一个兄弟节点。tag
:表示节点的类型,如函数组件、类组件、原生 DOM 元素等。pendingProps
和memoizedProps
:分别表示即将应用的属性和已经应用的属性。
-
双缓冲树
React Fiber 使用了双缓冲的 Fiber 树机制。在更新过程中,会构建一棵新的 Fiber 树(称为“workInProgress 树”),同时保留旧的 Fiber 树(“current 树”)。
当新树构建完成后,通过指针切换,瞬间将新树变为当前树进行渲染,避免了一次性大规模的 DOM 操作,提高了更新的效率和性能。
(1)首次执行
首次执行ReactDOM.render会创建fiberRootNode(源码中叫fiberRoot)和rootFiber。其中fiberRootNode是整个应用的根节点,rootFiber是所在组件树的根节点;
(2)render阶段
根据组件返回的JSX
在内存中依次创建Fiber
节点并连接在一起构建Fiber树
,被称为workInProgress Fiber
;
(3)alternate阶段
此时workInProgress fiber
已经构建完成,fiberRootNode
的current
指向了workInProgress fiber
(4)update阶段
假设p元素更新,这会开启一次新的render
阶段并构建一棵新的workInProgress Fiber 树
,且会尽可能复用现有的current Fiber
(5)alternate阶段
workInProgress fiber
在更换完后,fiberRootNode
的current
指针更换
3、实例分析
假设一个简单的 React 应用,包含一个父组件和多个子组件:
import React, { useState } from 'react';function ChildComponent({ index }) {return <div>Child {index}</div>;
}function ParentComponent() {const [count, setCount] = useState(0);const handleClick = () => {setCount(count + 1);};const childComponents = [];for (let i = 0; i < 10; i++) {childComponents.push(<ChildComponent key={i} index={i} />);}return (<div><button onClick={handleClick}>Increment</button>{childComponents}</div>);
}export default ParentComponent;
当用户点击按钮触发 setCount
状态更新时:
- React Fiber 开始协调更新过程。
- 从
ParentComponent
根节点对应的 Fiber 节点开始,进入工作循环。 - 遍历子组件,为每个
ChildComponent
创建或更新对应的 Fiber 节点。 - 如果在处理某个子组件的过程中,时间片用完或者有更高优先级的任务进来,React Fiber 会暂停当前工作,保存当前状态,等待下一次继续执行。
- 所有组件的 Fiber 节点处理完成后,构建出完整的
workInProgress
树。 - 最后,将新的
workInProgress
树切换为current
树进行渲染,用户界面得到更新。
总之,React Fiber 带来了更高效、更灵活的更新机制,使 React 能够更好地应对复杂的应用场景和用户需求。
五、任务调度循环和fiber构造循环区别
1、定义
(1)任务调度循环
源码位于Scheduler.js, 它是react应用得以运行的保证, 它需要循环调用, 控制所有任务(task)的调度.
(2)fiber构造循环
源码位于ReactFiberWorkLoop.js, 控制 fiber 树的构造, 整个过程是一个深度优先遍历.
这两个循环对应的 js 源码不同于其他闭包(运行时就是闭包), 其中定义的全局变量, 不仅是该作用域的私有变量, 更用于控制react应用的执行过程.
2、区别
任务调度循环
主要负责对更新任务进行调度和优先级管理。
任务调度循环是以二叉堆为数据结构(详见react 算法之堆排序), 循环执行堆的顶点, 直到堆被清空.
任务调度循环的逻辑偏向宏观, 它调度的是每一个任务(task), 而不关心这个任务具体是干什么的(甚至可以将Scheduler包脱离react使用), 具体任务其实就是执行回调函数performSyncWorkOnRoot或performConcurrentWorkOnRoot.
fiber构造循环
是以树为数据结构, 从上至下执行深度优先遍历(详见react 算法之深度优先遍历).
fiber构造循环的逻辑偏向具体实现, 它只是任务(task)的一部分(如performSyncWorkOnRoot包括: fiber树的构造, DOM渲染, 调度检测), 只负责fiber树的构造.
每个 Fiber 节点代表一个组件或者 DOM 节点的更新任务,Fiber 构造循环通过遍历这些节点来协调组件的更新和渲染。
3、联系
任务调度循环和 Fiber 构造循环在 React 中是紧密关联的,它们协同工作来实现高效的组件更新和页面渲染:
一、任务触发与传递
-
任务调度循环是更新任务的入口和管理者。当有更新事件发生(如用户交互、状态改变、网络数据获取等),任务调度循环首先感知到这些事件并将它们转化为相应的更新任务。
-
这些更新任务会被分配优先级,并根据优先级排队等待执行。当轮到某个任务执行时,任务调度循环会将任务传递给 Fiber 构造循环,启动组件树的更新过程。
例如,用户点击一个按钮触发了组件的状态更新,任务调度循环会捕获这个事件,将其包装成一个更新任务并确定其优先级。然后,当条件合适时,它会将这个任务传递给 Fiber 构造循环来开始处理组件树的更新。
二、时间片与可中断性协调
-
任务调度循环利用时间片的概念来管理任务的执行时间。它会根据浏览器的空闲时间和帧刷新率等因素,为每个任务分配一个时间片(通常是几毫秒)。
-
Fiber 构造循环在执行过程中会遵循任务调度循环分配的时间片。如果在一个时间片内无法完成当前的组件更新工作,Fiber 构造循环会暂停当前的工作,保存当前的状态和进度。
-
任务调度循环会在下一个合适的时间片再次启动 Fiber 构造循环,继续之前未完成的工作。这样的可中断性和时间片管理机制确保了页面在更新过程中仍然保持响应性,不会因为长时间的 JavaScript 执行而导致卡顿。
比如在更新一个复杂的组件树时,Fiber 构造循环可能在处理一个深层嵌套的组件时时间片用完。此时,它会暂停工作,任务调度循环会在后续的时间片中再次安排它继续执行。
三、优先级处理的一致性
- 任务调度循环和 Fiber 构造循环都遵循相同的优先级策略。高优先级的任务会在低优先级任务之前得到处理,以确保关键的用户交互和紧急的更新能够及时响应。
- 任务调度循环在任务排队时会根据优先级进行排序,而 Fiber 构造循环在遍历组件树时也会优先处理高优先级的组件更新。
- 例如,一个用户输入的即时响应任务(高优先级)和一个后台数据预取后的组件更新任务(低优先级),任务调度循环会首先安排高优先级任务执行,然后再考虑低优先级任务。在 Fiber 构造循环中,也会优先处理与高优先级任务相关的组件更新。
四、共同服务于页面渲染和用户体验
-
任务调度循环和 Fiber 构造循环的最终目标都是为了实现高效的页面渲染和良好的用户体验。
-
任务调度循环通过合理的任务管理和优先级调度,确保重要的更新任务能够及时执行,同时避免任务堆积和页面卡顿。
-
Fiber 构造循环通过高效的组件树更新和可中断的工作方式,使得页面在更新过程中能够保持响应,减少用户感知到的延迟和卡顿。
无论是在处理频繁的用户交互还是大规模的组件树更新,这两个循环相互配合,使得 React 应用能够在各种复杂情况下都能提供流畅的用户体验。
相关文章:

大厂进阶四:React源码Fiber架构解析
本文主要内容: 1、React Concurrent 2、React15架构 3、React16架构 4、Fiber架构 5、任务调度循环和fiber构造循环区别 一、React Concurrent React在解决CPU卡顿是会用到React Concurrent的概念,它是React中的一个重要特性和模块,主要的…...

MongoDB的WiredTiger存储引擎
作者:太阳 从MongoDB 3.2 开始,MongoDB实例默认的存储引擎为WiredTiger,WiredTiger存储引擎具体以下几大优点: 文档级并发 将数据持久化到磁盘 快照和checkpoint 数据压缩 本地数据加密 一、文档级别并发 1、WiredTiger使…...

windows 版本Jenkins的Jenkinsfile中共享变量
场景 jenkins部署在windows服务器上的,需要在Jenkinsfile中获取命令执行的结果存入一个变量,然后在后续的执行中使用此变量 一开始想的是定义一个环境变量,如下所示, pipeline {agent anystages {stage(test) {steps {bat for /…...

Android-->产物收集(含apk文件重命名, aab文件重命名)
以前写过修改apk生成路径和文件名的文章, 如下: AS–›Gradle 7.0.0/4.1.0/4.0/3.3/3.0 修改APK生成路径和文件名(附AAR修改方式以及分析过程)_com.android.build.gradle.internal.api.libraryvaria-CSDN博客 这种方法入侵了gradle,破坏了原有的gradle环境, 经常会导致如下问…...

matlab实现迷宫最佳路径规划
在MATLAB中实现迷宫路径的最佳路径规划,我们可以使用多种算法,其中最常见和高效的是A搜索算法(A Search Algorithm)。A*算法结合了最佳优先搜索和Dijkstra算法的优点,通过启发式函数来评估每个节点的优先级,…...

【自用】Python爬虫学习(二):网页解析的三种方式(re、bs4、xpath)
Python爬虫学习(二) 网页解析的三种方式1.正则表达式-re解析常用表达:re常用函数:在html中的运用: 2.BeautifulSoup解析常用语法:用法举例: 3.xpath解析示例代码1:示例代码2…...

从零到一:家政保洁小程序搭建全攻略与功能作用深度解析
目录 一、家政保洁小程序主要功能 二、家政保洁小程序搭建教程 (一)前期准备 (二)注册与选择工具 (三)设计与开发 (四)测试与优化 (五)发布与推广 一、…...

单元测试:为工程质量保驾护航
单元测试 单元测试是软件开发过程中确保代码质量和正确性的关键手段。它指的是对软件中的最小可测试单元(通常是函数或方法)进行验证,确保其行为符合预期。 基本概念 单元测试:验证软件中最小单元(通常是函数或方法…...

江协科技STM32学习笔记
第01章 STM32简介及开发环境搭建 1.1 STM32简介 1.1.1 STM32F103C8T6 系列:主流系列STM32F1 内核:ARM Cortex-M3 主频:72MHz RAM:20K(SRAM) ROM:64K(Flash) 供电…...

RabbitMQ再回首--往事如梦
这文章你就读吧,越读越🥸,一读一个不吱声 可靠的🐰警官:rabbitMQ,功能全面,不丢数据,体量小,容易堆积 声明exchange channel . exchangeDeclare ( String exchange , …...

头狼择校小程序
综述介绍 头狼择校,是头狼择™高校的简称,我们专注高校、大学的择校。倡导先嗅就业再择校,是预约工具和对话平台。帮您嗅招办、嗅教授、嗅学姐,预约择校有关的老师、顾问,助力考大学和考研的“双考”学生及家长了解就…...

【Electron】npm安装Electron项目失败报错问题和解决办法
前言 闲来无事,便想着研究一下Electron,没想到安装直接就卡住了 问题 npm ERR! RequestError: Hostname/IP does not match certificates altnames: Host: npm.taobao.org. is not in the certs altnames: DNS:*.tbcdn.cn, DNS:*.taobao.com, DNS:*.al…...

人工智能提示(prompt)工程入门
文章目录 人工智能提示(prompt)工程入门一、目的二、使用1、角色2、提示3、上下文4、例子5、输入6、输出 三、使用示例 人工智能提示(prompt)工程入门 一、目的 对于当前的发达的人工智能,我们可以广泛使用࿰…...

【机器学习的基本思想】模型优化与评估
【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科,通过算法和模型让计算机从数据中学习,进行模型训练和优化,做出预测、分类和决策支持。Python成为机器学习的首选语言,…...

公司电脑监控软件推荐(一口气了解8款!)一起领略电脑监控界的刀光剑影!
企业的内部管理的需求日益复杂,电脑监控软件作为提升工作效率、保障数据安全的重要工具,其重要性不言而喻。今天,我们将带您一口气了解8款顶尖的公司电脑监控软件,包括国内知名的“安企神”以及多款来自海外的优秀产品,…...

设备图纸资料管理系统:数字化转型下的高效协同与安全管理新篇章
在当今高度信息化的时代,设备图纸资料管理系统作为企业资产与知识管理的重要一环,正日益凸显其不可或缺的价值。这一系统集成了先进的数字化技术与管理理念,旨在实现设备图纸资料的高效存储、快速检索、安全共享及版本控制,为企业…...

ArcGIS基础:标注转注记及简单处理
注记是一个静态的标签图层,能够独立的保存为文件,并且具有计算功能; 标注是一个动态的标签图形,无法以文件的形式进行存储和计算; 2者各有优势和劣势,根据具体需求进行选择 需要注意的是注记要存储在GDB…...

jQuery实现图片轮播效果
实现图片轮播效果,打开页面,每隔3秒切换至下一张图片;光标移入数字时,播放相应图片。 思路: (1)获取需要轮播的图片和展示的div。 (2)使用animate设置left值ÿ…...

关于天地图新手使用
1分钟带你了解学习天地图 适用新手 天地图API (tianditu.gov.cn) 文档api 先去注册key 把脚本放到index.html文件里面 <!-- 天地图的官网申请的tk --> <script src="http://api.tianditu.gov.cn/api?v=4.0&tk=申请的key" type="text/javascr…...

STM32与Arduino和ESP32对比分析
在嵌入式系统领域,STM32、Arduino 和 ESP32 是三种广泛使用的微控制器平台。它们各自具有独特的优势,适用于不同类型的项目。本文将详细比较这些平台,帮助您了解它们之间的差异、优势以及可能的应用场景。 一、架构与处理能力 STM32…...

125. 验证回文串【 力扣(LeetCode) 】
一、题目描述 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字母和数字都属于字母数字字符。 给你一个字符串 s,如果它是 回文串 ,返回 true ;…...

3年经验,面试测试岗20k都拿不到了吗?
我的情况 大概介绍一下个人情况,女,本科,三年多测试工作经验,懂python,会写脚本,会selenium,会性能,然而到今天都没有收到一份offer!从年后就开始准备简历,年…...

【ML】强化学习(Reinforcement Learning)及其拆解
【ML】强化学习(Reinforcement Learning) 1. RL Outline 强化学习(Reinforcement Learning)概述1.1 RL的基本框架 2. RL 引入:从这个小游戏开始3. Policy Gradient 方法4. Actor-Critic 方法5. [奖励塑形(R…...

在宝塔面板下安装WordPress
宝塔面板是服务器管理好助手,尤其在Linux系统下,提高了管理的可视化,降低了Linux服务器的使用门槛。 WordPress是个非常好的博客系统,由于支持海量主题模板、各种类型的插件,因此已经成为建设各类网站的首选框架。 今…...

纷享销客CRM AI产品架构概览、产品特色
一、纷享销客CRM AI产品架构概览 纷享AI平台架构分为三个主要层次:AI基础设施层、AI平台层和AI应用层。每个层次都由一系列功能模块组成,旨在为客户提供强大的技术支持和灵活的解决方案。 1.Al基础设施层 AI基础设施层是整个AI平台的底层支撑ÿ…...

【文件IO】文件系统操作
文章目录 基本操作概述1. 文件属性2. 文件构造方法3. 文件方法1. 文件创建2. 文件删除3. 查看目录下所有的文件名4. 遍历目录5. 创建目录5. 目录重命名 基本操作概述 创建文件删除文件创建目录重命名文件判定文件存在… Java 中,提供了一个 File 类,进…...

Spring Cloud Alibaba 集成分布式定时任务调度功能
作者:千习 背景简介 定时任务是指在约定的时间,或者按照固定频率周期性执行的任务。在企业应用中,非用户行为发起的后台业务,一般都是通过定时任务来实现,常见场景如下: 异步数据处理:比如先…...

中职云计算实训室
一、实训室建设背景 随着信息技术的飞速发展,云计算已成为推动数字化转型、促进经济社会发展的重要力量。《中华人民共和国国民经济和社会发展第十四个五年规划和2035年远景目标纲要》明确提出,要加快数字化发展,建设数字中国。云计算作为数…...

【python制作一个小程序作为七夕礼物】
制作一个七夕节礼物的小程序,我们可以考虑一个简单的互动程序,比如一个“七夕情侣姓名配对指数计算器”。这个程序将接收两个名字作为输入,然后输出一个随机的“配对指数”和一些浪漫的话语。以下是一个使用Python实现的简单示例:…...

一篇文章教会你如何使用Haproxy,内含大量实战案例
1. Haproxy 介绍 HAProxy是法国开发者 威利塔罗(Willy Tarreau) 使用C语言编写的自由及开放源代码软件,是一款具备高并发(万级以上)、高性能的TCP和HTTP应用程序代理. HAProxy运行在当前的硬件上,可以支持…...