综合性门户网站有哪些/在线收录
reconcileChildren
1 )概述
- 在更新了一个节点之后,拿到它的props.children
- 要根据这个children里面的 ReactElement 来去创建子树的所有的 fiber 对象
- 要根据 props.children 来生成 fiber 子树,然后判断 fiber 对象它是否是可以复用的
- 因为我们在第一次渲染的时候,就已经渲染了整个 fiber 子树
- 再有一个更新进来之后,state 变化可能会导致一些子节点产生一个新的变化
- 可能就不能复用之前的 fiber 节点了,它里面的很多东西都变得不一样
- 大部分情况下所有 fiber 节点都是可以可以重复利用的
- 这个时候我们根据什么进行判断,是这里面的一个非常重要的一个点
- 在这里就会拿出react当中的非常重要的key,列表根据key来优化
2 )源码
在 packages/react-reconciler/src/ReactFiberBeginWork.js#L137 中
export function reconcileChildren(current: Fiber | null,workInProgress: Fiber,nextChildren: any,renderExpirationTime: ExpirationTime,
) {if (current === null) {// If this is a fresh new component that hasn't been rendered yet, we// won't update its child set by applying minimal side-effects. Instead,// we will add them all to the child before it gets rendered. That means// we can optimize this reconciliation pass by not tracking side-effects.workInProgress.child = mountChildFibers(workInProgress,null,nextChildren,renderExpirationTime,);} else {// If the current child is the same as the work in progress, it means that// we haven't yet started any work on these children. Therefore, we use// the clone algorithm to create a copy of all the current children.// If we had any progressed work already, that is invalid at this point so// let's throw it out.workInProgress.child = reconcileChildFibers(workInProgress,current.child,nextChildren,renderExpirationTime,);}
}
- 可见,根据 current 是否为 null 调用两个方法:
mountChildFibers
,reconcileChildFibers
- 两个方法的区别,在第二个参数
- 在前者方法中传递的是 null, 因为 第一次渲染,不存在 current.child
- 因为第一次渲染的时候,都是父亲节点先渲染,子节点后渲染
- 只有在后续的渲染过程当中,已经过第一次渲染了我们的父节点
- 这个时候才有一个子节点存在,所以这是一个区别
- 在 react-reconciler/src/ReactFiberBeginWork.js 中 的 reconcileChildren 调用这个
reconcileChildFibers
- 看一下这两个方法,它们来自于 ReactChildFiber.js
export const reconcileChildFibers = ChildReconciler(true); export const mountChildFibers = ChildReconciler(false);
- 可见,上述两个方法的区别是 参数的 true 和 false
- 这个参数的意思是: 表示是否要跟踪副作用
- 进入 ChildReconciler,这个方法 1k 多行,这里不去全部摘抄
- 用到哪里,逐个分析
整体框架
// 参数 shouldTrackSideEffects 表示是否要跟踪副作用
function ChildReconciler(shouldTrackSideEffects) {// ... 跳过很多代码// This API will tag the children with the side-effect of the reconciliation// itself. They will be added to the side-effect list as we pass through the// children and the parent.function reconcileChildFibers(returnFiber: Fiber,currentFirstChild: Fiber | null,newChild: any,expirationTime: ExpirationTime,): Fiber | null {// 省略很多代码// Remaining cases are all treated as empty.return deleteRemainingChildren(returnFiber, currentFirstChild);}return reconcileChildFibers;
}
-
在
ChildReconciler
方法的最后,return reconcileChildFibers;
,先看下这个方法// This API will tag the children with the side-effect of the reconciliation // itself. They will be added to the side-effect list as we pass through the // children and the parent. function reconcileChildFibers(returnFiber: Fiber,currentFirstChild: Fiber | null,newChild: any,expirationTime: ExpirationTime, ): Fiber | null {// This function is not recursive.// If the top level item is an array, we treat it as a set of children,// not as a fragment. Nested arrays on the other hand will be treated as// fragment nodes. Recursion happens at the normal flow.// Handle top level unkeyed fragments as if they were arrays.// This leads to an ambiguity between <>{[...]}</> and <>...</>.// We treat the ambiguous cases above the same.// newChild 是计算出来的 新children// 这个节点是一个 top level 的节点,因为 <></> 这种类型会匹配 REACT_FRAGMENT_TYPE// 符合以下就是没有key的 topLevel节点const isUnkeyedTopLevelFragment =typeof newChild === 'object' &&newChild !== null &&newChild.type === REACT_FRAGMENT_TYPE &&newChild.key === null;// 如果匹配了,那么 Fragment 是没有任何的操作更新的, 本身并没有什么实际的意义// 如果匹配了,则将newChild赋值if (isUnkeyedTopLevelFragment) {newChild = newChild.props.children;}// Handle object typesconst isObject = typeof newChild === 'object' && newChild !== null;// 如果是对象,说明有下面两种情况// 下面两种方法调用相似,都是基于 placeSingleChild 传递不同参数// 一个是 reconcileSingleElement// 另一个是 reconcileSinglePortalif (isObject) {switch (newChild.$$typeof) {// 匹配 REACT_ELEMENT,是通过 React.createElement 产生的case REACT_ELEMENT_TYPE:return placeSingleChild(reconcileSingleElement(returnFiber,currentFirstChild,newChild,expirationTime,),);// 匹配 REACT_PORTAL, 是通过 ReactDOM.createPortalcase REACT_PORTAL_TYPE:return placeSingleChild(reconcileSinglePortal(returnFiber,currentFirstChild,newChild,expirationTime,),);}}// 匹配到 string 和 number 类就是 text类型的Nodeif (typeof newChild === 'string' || typeof newChild === 'number') {return placeSingleChild(reconcileSingleTextNode(returnFiber,currentFirstChild,'' + newChild,expirationTime,),);}// 匹配到数组if (isArray(newChild)) {return reconcileChildrenArray(returnFiber,currentFirstChild,newChild,expirationTime,);}// 匹配到可迭代的对象if (getIteratorFn(newChild)) {return reconcileChildrenIterator(returnFiber,currentFirstChild,newChild,expirationTime,);}// 以上都没有匹配,但仍然是对象,则 throw errorif (isObject) {throwOnInvalidObjectType(returnFiber, newChild);}// 忽略 DEVif (__DEV__) {if (typeof newChild === 'function') {warnOnFunctionType();}}// 匹配到 undefined 的对象if (typeof newChild === 'undefined' && !isUnkeyedTopLevelFragment) {// If the new child is undefined, and the return fiber is a composite// component, throw an error. If Fiber return types are disabled,// we already threw above.switch (returnFiber.tag) {// 匹配到 ClassComponent 忽略case ClassComponent: {if (__DEV__) {const instance = returnFiber.stateNode;if (instance.render._isMockFunction) {// We allow auto-mocks to proceed as if they're returning null.break;}}}// Intentionally fall through to the next case, which handles both// functions and classes// eslint-disable-next-lined no-fallthrough// 匹配到 FunctionComponent 提醒case FunctionComponent: {const Component = returnFiber.type;invariant(false,'%s(...): Nothing was returned from render. This usually means a ' +'return statement is missing. Or, to render nothing, ' +'return null.',Component.displayName || Component.name || 'Component',);}}}// Remaining cases are all treated as empty.// 以上都不符合,则 是 null, 删除现有所有 children// 新的 props.children 都是 null, 老的 props 节点都应该被删除return deleteRemainingChildren(returnFiber, currentFirstChild); }
-
接下来看不同节点的更新
reconcileSingleElement
// 从当前已有的所有子节点中,找到一个可以复用新的子节点的Fiber对象 // 复用它之后,把剩下兄弟节点全部删掉 function reconcileSingleElement(returnFiber: Fiber,currentFirstChild: Fiber | null, // 是当前已有的fiber节点,初次渲染没有,后续渲染后很可能存在element: ReactElement,expirationTime: ExpirationTime, ): Fiber {// 获取 key 和 childconst key = element.key;let child = currentFirstChild;// child 存在while (child !== null) {// TODO: If key === null and child.key === null, then this only applies to// the first item in the list.if (child.key === key) {// 注意这个判断if (child.tag === Fragment? element.type === REACT_FRAGMENT_TYPE // 是否是 frament: child.elementType === element.type // 新老 element type) {// 删除 已存在当前节点的兄弟节点// 为何要删除兄弟节点,因为我们这次渲染只有一个节点,老的节点有兄弟节点,新的节点只有一个,删除之deleteRemainingChildren(returnFiber, child.sibling);const existing = useFiber(child,element.type === REACT_FRAGMENT_TYPE? element.props.children: element.props,expirationTime,);// 挂载属性existing.ref = coerceRef(returnFiber, child, element);existing.return = returnFiber;if (__DEV__) {existing._debugSource = element._source;existing._debugOwner = element._owner;}// 找到可复用节点,直接returnreturn existing;} else {// 条件不符合,删除节点并退出 deleteRemainingChildren(returnFiber, child);break;}} else {// key 不同,则删除deleteChild(returnFiber, child);}// 当前兄弟节点 等于 child 再次进入while循环child = child.sibling;}// 创建新的节点, 基于各种不同的类型,调用不同的创建 Fiber的方式if (element.type === REACT_FRAGMENT_TYPE) {const created = createFiberFromFragment(element.props.children, // 注意这个参数returnFiber.mode,expirationTime,element.key,);created.return = returnFiber;return created;} else {const created = createFiberFromElement(element,returnFiber.mode,expirationTime,);created.ref = coerceRef(returnFiber, currentFirstChild, element);created.return = returnFiber;return created;} }
- 进入
createFiberFromFragment
export function createFiberFromFragment(elements: ReactFragment,mode: TypeOfMode,expirationTime: ExpirationTime,key: null | string, ): Fiber {const fiber = createFiber(Fragment, elements, key, mode);fiber.expirationTime = expirationTime;return fiber; }// This is a constructor function, rather than a POJO constructor, still // please ensure we do the following: // 1) Nobody should add any instance methods on this. Instance methods can be // more difficult to predict when they get optimized and they are almost // never inlined properly in static compilers. // 2) Nobody should rely on `instanceof Fiber` for type testing. We should // always know when it is a fiber. // 3) We might want to experiment with using numeric keys since they are easier // to optimize in a non-JIT environment. // 4) We can easily go from a constructor to a createFiber object literal if that // is faster. // 5) It should be easy to port this to a C struct and keep a C implementation // compatible. const createFiber = function(tag: WorkTag,pendingProps: mixed, // 对于 fragment来说,props只有children, 直接把children作为propskey: null | string,mode: TypeOfMode, ): Fiber {// $FlowFixMe: the shapes are exact here but Flow doesn't like constructorsreturn new FiberNode(tag, pendingProps, key, mode); };
- 以上的 fragment 可以在 ReactFiberBeginWork.js 中的 updateFragment 方法中找到验证
function updateFragment(current: Fiber | null,workInProgress: Fiber,renderExpirationTime: ExpirationTime, ) {// 看这里,直接通过 .pendingProps 而非 props.children 获取,参考上述 createFiber 写明原因const nextChildren = workInProgress.pendingProps;reconcileChildren(current,workInProgress,nextChildren,renderExpirationTime,);return workInProgress.child; }
- 进入
createFiberFromElement
export function createFiberFromElement(element: ReactElement,mode: TypeOfMode,expirationTime: ExpirationTime, ): Fiber {let owner = null;if (__DEV__) {owner = element._owner;}// 获取各类属性const type = element.type;const key = element.key;const pendingProps = element.props;// 创建 Fiberconst fiber = createFiberFromTypeAndProps(type,key,pendingProps,owner,mode,expirationTime,);if (__DEV__) {fiber._debugSource = element._source;fiber._debugOwner = element._owner;}return fiber; }
- 进入
createFiberFromTypeAndProps
// 这个方法比较复杂,要判断不同的 type 给 fiber 对象增加 不同的 tag // 主要是去匹配 fiberTag export function createFiberFromTypeAndProps(type: any, // React$ElementTypekey: null | string,pendingProps: any,owner: null | Fiber,mode: TypeOfMode,expirationTime: ExpirationTime, ): Fiber {let fiber;// 组件tag未知时的初始化配置 未指定状态let fiberTag = IndeterminateComponent;// The resolved type is set if we know what the final type will be. I.e. it's not lazy.let resolvedType = type;// 根据不同类型来处理 fiberTagif (typeof type === 'function') {// 判断是否有 constructor 方法/*function shouldConstruct(Component: Function) {const prototype = Component.prototype;// 注意,这里 isReactComponent 是一个 {}return !!(prototype && prototype.isReactComponent);}*/if (shouldConstruct(type)) {fiberTag = ClassComponent;}} else if (typeof type === 'string') {fiberTag = HostComponent;} else {getTag: switch (type) {case REACT_FRAGMENT_TYPE:return createFiberFromFragment(pendingProps.children,mode,expirationTime,key,);case REACT_CONCURRENT_MODE_TYPE:return createFiberFromMode(pendingProps,mode | ConcurrentMode | StrictMode,expirationTime,key,);case REACT_STRICT_MODE_TYPE:return createFiberFromMode(pendingProps,mode | StrictMode,expirationTime,key,);case REACT_PROFILER_TYPE:return createFiberFromProfiler(pendingProps, mode, expirationTime, key);case REACT_SUSPENSE_TYPE:return createFiberFromSuspense(pendingProps, mode, expirationTime, key);default: {if (typeof type === 'object' && type !== null) {switch (type.$$typeof) {case REACT_PROVIDER_TYPE:fiberTag = ContextProvider;break getTag;case REACT_CONTEXT_TYPE:// This is a consumerfiberTag = ContextConsumer;break getTag;case REACT_FORWARD_REF_TYPE:fiberTag = ForwardRef;break getTag;case REACT_MEMO_TYPE:fiberTag = MemoComponent;break getTag;case REACT_LAZY_TYPE:fiberTag = LazyComponent;resolvedType = null;break getTag;}}let info = '';if (__DEV__) {if (type === undefined ||(typeof type === 'object' &&type !== null &&Object.keys(type).length === 0)) {info +=' You likely forgot to export your component from the file ' +"it's defined in, or you might have mixed up default and " +'named imports.';}const ownerName = owner ? getComponentName(owner.type) : null;if (ownerName) {info += '\n\nCheck the render method of `' + ownerName + '`.';}}invariant(false,'Element type is invalid: expected a string (for built-in ' +'components) or a class/function (for composite components) ' +'but got: %s.%s',type == null ? type : typeof type,info,);}}}// 最终创建 Fiberfiber = createFiber(fiberTag, pendingProps, key, mode);fiber.elementType = type;fiber.type = resolvedType;fiber.expirationTime = expirationTime;return fiber; }
- 以上,
reconcileSingleElement
就完了
- 进入
-
进入
reconcileSingleTextNode
function reconcileSingleTextNode(returnFiber: Fiber,currentFirstChild: Fiber | null,textContent: string,expirationTime: ExpirationTime, ): Fiber {// There's no need to check for keys on text nodes since we don't have a// way to define them.// 处理 原生 标签if (currentFirstChild !== null && currentFirstChild.tag === HostText) {// We already have an existing node so let's just update it and delete// the rest.// 删除兄弟节点,新节点只是一个纯的文本节点deleteRemainingChildren(returnFiber, currentFirstChild.sibling);// 基于 useFiber 复用当前节点const existing = useFiber(currentFirstChild, textContent, expirationTime);existing.return = returnFiber;return existing;}// The existing first child is not a text node so we need to create one// and delete the existing ones.deleteRemainingChildren(returnFiber, currentFirstChild);const created = createFiberFromText(textContent,returnFiber.mode,expirationTime,);created.return = returnFiber;return created; }
- 这个流程就比较简单了
-
现在我们主要看下
deleteRemainingChildren
这个apifunction deleteRemainingChildren(returnFiber: Fiber, // 当前正在更新的节点currentFirstChild: Fiber | null, // 子节点 ): null {// 这是第一次渲染的时候,没有子节点// 直接 returnif (!shouldTrackSideEffects) {// Noop.return null;}// TODO: For the shouldClone case, this could be micro-optimized a bit by// assuming that after the first child we've already added everything.// 一个个的删除let childToDelete = currentFirstChild;while (childToDelete !== null) {deleteChild(returnFiber, childToDelete);childToDelete = childToDelete.sibling;}return null; }
- 进入
deleteChild
// 可以看到这里没有实施删除的操作,只是改变了节点上的 effectTag // 这里我们只更新 Fiber Tree, 如果真的要 delete 就会影响到 dom节点 // 所以删除的流程不在这里做,只有在下个阶段,也就是 commit 阶段来做 // 就是把Fiber Tree 需要更新的流程都过一遍之后,把整个需要更新的属性 // 通过 firstEffect,lastEffect 这种链条,最终链到根节点上面 // 最终要执行更新 只需要在 commit 阶段拿到 根节点上面的 这种链条把每个节点去执行即可 // 在处理更新的时候任务是可以中断的,但是在 commit 阶段任务是不可中断的 function deleteChild(returnFiber: Fiber, childToDelete: Fiber): void {if (!shouldTrackSideEffects) {// Noop.return;}// Deletions are added in reversed order so we add it to the front.// At this point, the return fiber's effect list is empty except for// deletions, so we can just append the deletion to the list. The remaining// effects aren't added until the complete phase. Once we implement// resuming, this may not be true.const last = returnFiber.lastEffect;// 存在 lastif (last !== null) {last.nextEffect = childToDelete;returnFiber.lastEffect = childToDelete;} else {// 不存在 lastreturnFiber.firstEffect = returnFiber.lastEffect = childToDelete;}childToDelete.nextEffect = null; // 已经是要删除的节点,上面的其他副作用都是没有任何意义的// effectTag 就是告诉后续的 commit 阶段,对于这个节点需要执行什么操作,可以看到,这里是删除childToDelete.effectTag = Deletion; // 只需要设置这个即可 }
- 进入
-
reconcileChildrenArray
和reconcileChildrenIterator
这两个api比较复杂,先跳过 -
其他的 API 都是比较简单了
相关文章:

React16源码: React中的reconcileChildren的源码实现
reconcileChildren 1 )概述 在更新了一个节点之后,拿到它的props.children要根据这个children里面的 ReactElement 来去创建子树的所有的 fiber 对象要根据 props.children 来生成 fiber 子树,然后判断 fiber 对象它是否是可以复用的 因为我…...

幻兽帕鲁Docker服务端搭建
幻兽帕鲁Docker服务端搭建 各种命令 https://bbs.saraba1st.com/2b/thread-2168983-1-1.html 存档恢复 这里直接看这个工程的readme就行:https://github.com/yoko-murasame/palworld-host-save-fix 其他参考:https://forum.gamer.com.tw/C.php?bsn7…...

【ARM Cortex-M 系列 1.1 -- Cortex-M33 与 M4 差异 详细介绍】
请阅读【嵌入式开发学习必备专栏 之 Cortex-Mx 专栏】 文章目录 背景Cortex-M33 与 M4 差异Cortex-M33Cortex-M4关系和差异举例说明 背景 在移植 RT-Thread 到 瑞萨RA4M2(Cortex-M33)上时,遇到了hardfault 问题,最后使用了Cortex…...

docker 部署及命令
一、容器概述 1、为什么要用到容器? ①容器可以屏蔽底层操作系统的差异性,让业务应用不管在哪里都是使用容器的环境运行,从而保证开发测试环境与生产环境的一致性 ②容器部署起来非常便捷和迅速,缩短开发测试部署的周期时间 2…...

API接口安全总结
接口分类 HTTP接口 RPC接口(客户端和服务器端的连接 例如游戏登陆)非web协议,PRC 远程过程调用 Remote Procedure Call,其就是一个节点请求另外一个节点提供的服务。当两个物理分离的子系统需要建立逻辑上的关联时,R…...

性能优化-HVX 指令介绍
「发表于知乎专栏《移动端算法优化》」 本文主要介绍了 HVX 指令相关的知识,包括 HVX 寄存器相关内容,指令的背景依赖,部分常用 intrinsic HVX 指令。具体指令的详细内容及使用还需阅读 HVX 的指令文档,以及细致的实践操作。 &…...

web安全思维导图(白帽子)
web安全思维导图(白帽子) 客户端脚本安全 服务端应用安全 白帽子讲web安全 安全运营体系建设...

美,英,法,德、意大利和西班牙的geojson,以及区域json
美,英,法,德、意大利和西班牙的geojson文件 json地址 https://pan.baidu.com/s/1nio1bV_j-jAEVqgEHXWsNw?pwdqwer#list/path/GEOJSON 感谢大佬提供的 大佬连接 大佬的知乎原地址 国内geojson获取工具地址 http://da
JavaEE-微服务-Vuex
Vuex 2.1 什么是Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。 Vuex在组件之间共享数据。 2.2 使用 vue cli 构建项目 2.3 入门案例 2.3.1 定义数据 export default new Vuex.Store({state: { // 状态区域(定义变量区域)user: ,toke…...

在Windows虚拟机中挂载IP代理的流程
在虚拟机中挂载IP代理的步骤通常依赖于所使用的虚拟机软件(如VMware、VirtualBox等)以及代理服务器类型(HTTP/HTTPS/SOCKS)。以下是一个通用流程: 在Windows虚拟机中设置网络代理以使用代理IP: 1. SOCKS或H…...

软考之软件工程
一、瀑布模型 严格区分阶段,每个阶段因果关系紧密相连,只适合需求明确的项目 缺点:软件需求完整性、正确性难确定;严格串行化,很长时间才能看到结果;瀑布模型要求每个阶段一次性完全解决该阶段工作…...

微信小程序(六)tabBar的使用
注释很详细,直接上代码 上一篇 新增内容: 1. 标签栏文字的内容以及默认与选中颜色 2. 标签栏图标的默认样式与选中样式 3. 标签选项路径页面 4.标签栏背景颜色 🐼(文末补充)设置标签栏后为什么navigator标签无法跳转页…...

写Shell以交互方式变更Ubuntu的主机名
以下是一个简单的 Bash 脚本,用于以交互方式更改 Ubuntu 20 系统的主机名: 1#!/bin/bash 2 3# 提示用户输入新的主机名 4read -p "请输入新的系统名称(主机名): " new_hostname 5 6# 检查是否输入了新的主机名 7if [ -…...

SpringBoot整合ElasticSearch实现基础的CRUD操作
本文来说下SpringBoot整合ES实现CRUD操作 文章目录 概述spring-boot-starter-data-elasticsearch项目搭建ES简单的crud操作保存数据修改数据查看数据删除数据 本文小结 概述 SpringBoot支持两种技术和es交互。一种的jest,还有一种就是SpringData-ElasticSearch。根据…...

【PyTorch】记一次卷积神经网络优化过程
记一次卷积神经网络优化过程 前言 在深度学习的世界中,图像分类任务是一个经典的问题,它涉及到识别给定图像中的对象类别。CIFAR-10数据集是一个常用的基准数据集,包含了10个类别的60000张32x32彩色图像。在上一篇博客中,我们已…...

C++面试宝典第24题:袋鼠过河
题目 一只袋鼠要从河这边跳到河对岸,河很宽,但是河中间打了很多桩子。每隔一米就有一个桩子,每个桩子上都有一个弹簧,袋鼠跳到弹簧上就可以跳得更远。每个弹簧力量不同,用一个数字代表它的力量,如果弹簧力量为5,就代表袋鼠下一跳最多能够跳5米;如果为0,就会陷进去无法…...

2401vim,vim标号
标号简介 提供高亮,快速告诉用户有用信息.如,调试器在左侧列中有个表示断点的图标. 另一例可能是表示(PC)程序计数器的箭头.标号功能允许在窗口左侧放置标号或图标,并定义应用行的高亮. 此外,调试器还支持8到10种不同的标号和高亮颜色,见|NetBeans|. 使用标号有两个步骤: 1…...

Web开发中HTTP请求、响应等相关知识
目录 params和data区别? post请求可以使用params吗? put、delete请求应该使用params还是data? get和post的区别? 常用注解使用 params和data区别? 在使用Ajax时,"params" 和 "data" 通常用于不同的上下文。 "params…...

[Android] Android文件系统中存储的内容有哪些?
文章目录 前言root 文件系统/system 分区稳定性:安全性: /system/bin用来提供服务的二进制可执行文件:调试工具:UNIX 命令:调用 Dalvik 的脚本(upall script):/system/bin中封装的app_process脚本 厂商定制的二进制可执行文件: /system/xbin/system/lib[64]/system/…...

透明拼接屏在汽车领域的应用
随着科技的进步,透明拼接屏作为一种新型的显示技术,在汽车领域的应用越来越广泛。尼伽小编将围绕透明拼接屏在汽车本身、4S店、展会、工厂等方面的应用进行深入探讨,并展望未来的设计方向。 一、透明拼接屏在汽车本身的应用 车窗显示&#x…...

“深入理解RabbitMQ交换机的原理与应用“
深入理解RabbitMQ交换机的原理与应用 引言1. RabbitMQ交换机简介介绍1.1 什么是RabbitMQ?1.1.1 消息中间件的作用1.1.2 RabbitMQ的特点和优势 1.2 RabbitMQ的基本概念1.2.1 队列1.2.2 交换机1.2.3 路由键 1.3 交换机的作用和分类1.3.1 直连交换机(direct…...

Programming Abstractions in C阅读笔记:p248-p253
《Programming Abstractions in C》学习第69天,p248-p253总结,总计6页。 一、技术总结 “A generalized program for two-player games”如标题所示,该小节强调要学会从一个复杂的程序中抽象出通用的内容——这也是本书的主旨——“Program…...

面试题目,你对前端工程化的了解
前端工程化是通过工具和流程来提高软件开发效率、降低维护成本以及改善项目可维护性的方法。在前端领域,前端工程化通常包括以下方面内容 版本控制 使用 git 来管理代码的版本,追踪变更,协作开发等项目脚手架 使用项目的脚手架进行项目的初始…...

2023年春秋杯网络安全联赛冬季赛 Writeup
文章目录 Webezezez_phppicup Misc谁偷吃了外卖modules明文混淆 Pwnnmanagerbook Reupx2023 CryptoCF is Crypto Faker 挑战题勒索流量Ezdede 可信计算 Web ezezez_php 反序列化打redis主从复制RCE:https://www.cnblogs.com/xiaozi/p/13089906.html <?php c…...

docker安装Rabbitmq教程(详细图文)
目录 1.下载Rabbitmq的镜像 2.创建并运行rabbitmq容器 3.启动web客户端 4.访问rabbitmq的微博客户端 5.遇到的问题 问题描述:在rabbitmq的web客户端发现界面会弹出如下提示框Stats in management UI are disabled on this node 解决方法 (1&#…...

java web mvc-05-JSF JavaServer Faces 入门例子
拓展阅读 Spring Web MVC-00-重学 mvc mvc-01-Model-View-Controller 概览 web mvc-03-JFinal web mvc-04-Apache Wicket web mvc-05-JSF JavaServer Faces web mvc-06-play framework intro web mvc-07-Vaadin web mvc-08-Grails 开源 The jdbc pool for java.(java …...

yolov8 训练voc数据集
yolov8训练 from ultralytics import YOLO# 加载模型 # model YOLO(yolov8n.yaml) # 从YAML构建新模型 # model YOLO(yolov8n.pt) # 加载预训练模型(推荐用于训练) model YOLO(yolov8n.yaml).load(yolov8n.pt) # 从YAML构建并转移权重# 训练模型…...

Python笔记12-多线程、网络编程、正则表达式
文章目录 多线程网络编程正则表达式 多线程 现代操作系统比如Mac OS X,UNIX,Linux,Windows等,都是支持“多任务”的操作系统。 进程: 就是一个程序,运行在系统之上,那么便称之这个程序为一个运…...

X射线中关于高频高压发生器、高清晰平板探测器、大热容量X射线球管、远程遥控系统的解释
高频高压发生器(High Frequency High Voltage Generator) 在医用诊断X射线设备中扮演着关键角色,它主要用于产生并控制用于X射线成像的高压电能。 这种发生器采用高频逆变技术,通过将输入的低电压、大电流转换为高电压、小电流&am…...

【算法】最短路计数(搜索)复习
题目 给出一个 N 个顶点 M 条边的无向无权图,顶点编号为 1 到 N。 问从顶点 1 开始,到其他每个点的最短路有几条。 输入格式 第一行包含 2 个正整数 N,M,为图的顶点数与边数。 接下来 M 行,每行两个正整数 x,y,表…...