农业公司怎样建立网站/重庆关键词优化平台
completeUnitOfWork
1 )概述
- 各种不同类型组件的一个更新过程对应的是在执行
performUnitOfWork
里面的beginWork
阶段 - 它是去向下遍历一棵 fiber 树的一侧的子节点,然后遍历到叶子节点为止,以及 return 自己 child 的这种方式
- 在
performUnitOfWork
里面,还有一个方法叫做completeUnitOfWork
- 在
completeUnitOfWork
中会根据是否有中断,调用不同的一个处理方法 - 什么叫中断呢?
- 就是我们在渲染一个组件的时候,出现了错误的场景进行处理
- 或者优先级被更高优先级打断,低优先级转移到下一次处理
- 在
renderRoot
当中, 使用try catch
去调用workLoop
去循环每一个节点的 workLoop
里面调用的就是performUnitOfWork
- 在
performUnitOfWork
里面调用了beginWork
- 它里面就是执行各种不同组件的一个update的一个过程
- 在后面
completeUnitOfWork
,是处理到一侧的子节点遍历到最下层的时候,它没有子节点可以返回了 - 因为
beginWork
里面调用了各种update,它们都是return自己的child - 比如说,有这么一棵 fiber 树的一个情况的时候

- 我们先去对
RootFiber
执行了beginWork
,然后执行了之后 return 的是它的 child,也就是App
- 一层一层这么执行下来之后,到了有分叉节点,也就是说一个节点,下面有多个子节点的情况
- 它 return 的还是它的第一个 child 节点,所以这个时候,后面的节点是没有被执行到更新的
- 因为 inpput 它返回了之后,返回的是它里面的 input child 这个节点
- 到这里为止,这个 dom 的 input 节点,已经没有child了,这个时候就 return null
- 因为它的 child是 null,所以在这里首先执行的是
beginWork
- 如果有child,它就会一直往child方向进行一个查找
- 等到 next 等于 null 的情况的时候,就会去执行
completeUnitOfWork
completeUnitOfWork
就是对当前这个input界定 执行它的complete,具体执行什么- 在
beginWork
的过程当中,如果我们去update某一个节点的时候,有报错了 - 或者是 throw 了一个 promise, 就是 suspend 的情况, 它会执行一定的标记
- 在
renderRoot
当中,我们可以看到它如果有报错,它的catch是要在renderRoot
里面被捕获的这个错误 - 对这个错误补获之后,它是有一定的处理的, 处理完之后,它仍然处于这个
while
循环当中,它里面并没有 break- 位置:
packages/react-reconciler/src/ReactFiberScheduler.js#L1276
- 位置:
- 这个时候它还是会往下进行一个执行的,只不过它会在里面给我们当前这个节点去执行一个标记
- 在
completeUnitOfWork
的阶段,会对有各种不同标记的一个节点,执行不同的方法 - 主要的是我们正常流程走的是叫
completeWork
这么一个方法 - 而对于有异常的节点,它的一个流程是调用一个叫
unwindWork
的方法 - 然后会判断是否有兄弟节点来执行不同的操作
- 比如执行到上图 input 这个节点的
completeUnitOfWork
之后,它没有兄弟节点 - 它直接去执行它的父节点,也就是 Input 组件的
completeUnitOfWork
- 在这里,我们发现它是有兄弟节点的,因为第一次update的过程,是往下的
- 对于旁边的
List
节点是没有任何更新的, 这个时候我们就会返回它的兄弟节点List
- 比如执行到上图 input 这个节点的
- 对于这个兄弟节点, 继续对它执行一个update的一个过程,也就是
beginWork
的一个过程 - 这就是在
completeUnitOfWork
里面非常重要的一个判断条件- 就是如果有兄弟节点,它会直接返回这个兄弟节点
- 完成节点之后要赋值整个effect链
- effect是非常重要的,后面即将要把所有的更新结束的节点,挂载到真正的dom上面
- 这一个阶段叫做commit阶段,它要去执行每一个节点不同的跟dom有关的操作
- 在前面
beginWork
和completeUnitOfWork
,对每一个节点的更新过程标记了 - 有哪些 SideEffect 最终要被commit的一个过程
- 在
completeUnitOfWork
里面会完成这一步,把所有的effect节点进行一个串联 - 让
commitWork
的阶段可以非常方便的根据这个链去执行每一个节点的最终的操作
2 ) 源码
定位到 packages/react-reconciler/src/ReactFiberScheduler.js#L939
找到 completeUnitOfWork
// 这个API 是在 workInProgress 的基础上进行的一个操作
function completeUnitOfWork(workInProgress: Fiber): Fiber | null {// Attempt to complete the current unit of work, then move to the// next sibling. If there are no more siblings, return to the// parent fiber.// 进来首先就是一个 while true 的一个循环while (true) {// The current, flushed, state of this fiber is the alternate.// Ideally nothing should rely on this, but relying on it here// means that we don't need an additional field on the work in// progress.// 对于这个循环, 它首先获取currentconst current = workInProgress.alternate;if (__DEV__) {ReactCurrentFiber.setCurrentFiber(workInProgress);}// 然后 获取 returnFiber 和 siblingFiber,也就是它的父节点以及它的兄弟节点// 这个在后面我们判断是否要返回兄弟节点的时候就会用到const returnFiber = workInProgress.return;const siblingFiber = workInProgress.sibling;// 这里首先一进来就有一个大的判断,它是一个整个方法里面最大的一个判断// Incomplete 就是这个节点它是出现了错误,然后被捕获的, 并标记这个 sideEffect// 逻辑与操作来判断某一个属性上面它是否有某一个特性的一个方式if ((workInProgress.effectTag & Incomplete) === NoEffect) {if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {// Don't replay if it fails during completion phase.mayReplayFailedUnitOfWork = false;}// This fiber completed.// Remember we're completing this unit so we can find a boundary if it fails.nextUnitOfWork = workInProgress;if (enableProfilerTimer) {if (workInProgress.mode & ProfileMode) {startProfilerTimer(workInProgress);}nextUnitOfWork = completeWork(current,workInProgress,nextRenderExpirationTime,);if (workInProgress.mode & ProfileMode) {// Update render duration assuming we didn't error.stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false);}} else {nextUnitOfWork = completeWork(current,workInProgress,nextRenderExpirationTime,);}if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {// We're out of completion phase so replaying is fine now.mayReplayFailedUnitOfWork = true;}stopWorkTimer(workInProgress);resetChildExpirationTime(workInProgress, nextRenderExpirationTime);if (__DEV__) {ReactCurrentFiber.resetCurrentFiber();}if (nextUnitOfWork !== null) {// Completing this fiber spawned new work. Work on that next.return nextUnitOfWork;}// 接下去这个个判断,是要构造一个所有 有 SideEffect 的节点的一个链状的结构// 这个链状结构最终是用于 commitWork 的时候用来进行对这些有 SideEffect的节点进行 commit 的一个操作,// 这边它的一个判断条件,returnFiber不等于null,并且returnFiber它不是一个 Incomplete 的一个节点// 因为对于一个 Incomplete 的节点,它唯一可以具有的一个SideEffect,就是这个节点已经被捕获了// 因为对于有 Incomplete 错误的节点是不会渲染正常的子节点的if (returnFiber !== null &&// Do not append effects to parents if a sibling failed to complete(returnFiber.effectTag & Incomplete) === NoEffect) {// Append all the effects of the subtree and this fiber onto the effect// list of the parent. The completion order of the children affects the// side-effect order.// 对于正常的一个情况, 首先要判断一下 returnFiber.firstEffect 是否等于 null// 符合判断就代表 现在这个 returnFiber 上还没有记录任何它的子节点的有副作用的子节点// 这个时候, 直接把当前节点的firstEffect赋值给 returnFiber.firstEffect// 因为它之前是没有任何一个的嘛,我们这边真正要做的是把当前节点的 firstEffect 到 lastEffect的一个链条// 这个单项链表,给它挂载到它的父节点的同样的一个 firstEffect到lastEffect的单项链表的最后if (returnFiber.firstEffect === null) {returnFiber.firstEffect = workInProgress.firstEffect;}// 就是下面这一段判断,就是来做这个事情的, 如果returnFiber.lastEffect不等于null,那说明它已经有了// 那么对于returnFiber上面有记录过别的 SideEffect 的节点之后// 我们当前节点是挂载到整个 SideEffect 链的最后,就是下面这样,就是把它连到最后的上面if (workInProgress.lastEffect !== null) {if (returnFiber.lastEffect !== null) {returnFiber.lastEffect.nextEffect = workInProgress.firstEffect;}// 还要操作如下,因为它的这个(returnFiber.lastEffect)指针目前还指向它原来的那个lastEffect// 在 赋值 nextEffect之后,它的最后一个就是这个链的最后一个已经变成 workInProgress.lastEffect,所以这边要执行这么一个操作// 当然这个条件是要建立在 workInProgress.lastEffect 是有值的情况// 这是把它们各自的firsteffect到lasteffect,这个链给它进行一个串联的过程returnFiber.lastEffect = workInProgress.lastEffect;}// If this fiber had side-effects, we append it AFTER the children's// side-effects. We can perform certain side-effects earlier if// needed, by doing multiple passes over the effect list. We don't want// to schedule our own side-effect on our own list because if end up// reusing children we'll schedule this effect onto itself since we're// at the end.// 对于returnFiber来说,当前这个节点也可能是有副作用的,那么这边就接下去就会做这个操作// 如果当前节点的 effectTag > PerformedWork 的,因为 PerformedWork 是一个给 DEVTool 用的一个 sideEffect// 对于真正的react更新是没有任何意义的, 所以如果它仅仅只有 PerformedWork ,它就不是一个有效的 SideEffect 的节点const effectTag = workInProgress.effectTag;// Skip both NoWork and PerformedWork tags when creating the effect list.// PerformedWork effect is read by React DevTools but shouldn't be committed.if (effectTag > PerformedWork) {// 如果它有 SideEffect,就把当前节点作为父节点的 SideEffect 链的最后一个给它挂载上去// 或者如果是当前父节点没有任何记录的 SideEffect,它就是第一个if (returnFiber.lastEffect !== null) {returnFiber.lastEffect.nextEffect = workInProgress;} else {returnFiber.firstEffect = workInProgress;}returnFiber.lastEffect = workInProgress;}}if (__DEV__ && ReactFiberInstrumentation.debugTool) {ReactFiberInstrumentation.debugTool.onCompleteWork(workInProgress);}if (siblingFiber !== null) {// If there is more work to do in this returnFiber, do that next.return siblingFiber;} else if (returnFiber !== null) {// If there's no more work in this returnFiber. Complete the returnFiber.workInProgress = returnFiber;continue;} else {// We've reached the root.return null;}} else {if (enableProfilerTimer && workInProgress.mode & ProfileMode) {// Record the render duration for the fiber that errored.stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false);// Include the time spent working on failed children before continuing.let actualDuration = workInProgress.actualDuration;let child = workInProgress.child;while (child !== null) {actualDuration += child.actualDuration;child = child.sibling;}workInProgress.actualDuration = actualDuration;}// This fiber did not complete because something threw. Pop values off// the stack without entering the complete phase. If this is a boundary,// capture values if possible.const next = unwindWork(workInProgress, nextRenderExpirationTime);// Because this fiber did not complete, don't reset its expiration time.if (workInProgress.effectTag & DidCapture) {// Restarting an error boundarystopFailedWorkTimer(workInProgress);} else {stopWorkTimer(workInProgress);}if (__DEV__) {ReactCurrentFiber.resetCurrentFiber();}if (next !== null) {stopWorkTimer(workInProgress);if (__DEV__ && ReactFiberInstrumentation.debugTool) {ReactFiberInstrumentation.debugTool.onCompleteWork(workInProgress);}// If completing this work spawned new work, do that next. We'll come// back here again.// Since we're restarting, remove anything that is not a host effect// from the effect tag.next.effectTag &= HostEffectMask;return next;}if (returnFiber !== null) {// Mark the parent fiber as incomplete and clear its effect list.returnFiber.firstEffect = returnFiber.lastEffect = null;returnFiber.effectTag |= Incomplete;}if (__DEV__ && ReactFiberInstrumentation.debugTool) {ReactFiberInstrumentation.debugTool.onCompleteWork(workInProgress);}// 存在 sibling 节点, 注意这边是return,也就是跳出while循环if (siblingFiber !== null) {// If there is more work to do in this returnFiber, do that next.return siblingFiber;} else if (returnFiber !== null) {// If there's no more work in this returnFiber. Complete the returnFiber.// 如果returnFiber不等于null,那么 workInProgress = returnFiber// 比如对于最上面示例图的 input节点,它的 completeUnitOfWork// 如果它没有兄弟节点,那么它就继续执行Input的 completeUnitOfWork// 这个循环是在 completeUnitOfWork 内部进行的一个过程workInProgress = returnFiber;continue;} else {// 如果 returnFiber 也等于null,那么它直接 return null// 说明已经到达顶点了,就到达 RootFiber 了,我们的更新过程呢已经完成了// 只需要在接下去 commitRoot 就可以了return null;}}}// Without this explicit null return Flow complains of invalid return type// TODO Remove the above while(true) loop// eslint-disable-next-line no-unreachablereturn null;
}
- 对于这个while循环里面,其实它的所有代码都是在if else里面的
- if else它们最大的一个区别是什么呢?
- 在if里面我们可以看这边这个特殊情况
- 就是 nextUnitOfWork 等于 completeWork,然后传入一些属性
- 对于 else 的情况,这边调用了 next = unwindWork
- 这就是对于一个是否有抛出过错误的一个节点,执行的一个不同的操作
- completeWork,是没有任何一个错误的一个节点,它的一个complete的一个过程
- 调用了completework,就是把这个节点的更新给它完成了
- unwindWork 是有节点的错误,被捕获,如何去处理的一个过程
- 在上面的 SideEffect 到底有什么意义呢?
- 比如有如下场景:
- 有个列表上有值为 1, 2, 3的三个节点
- 点击 button 按钮,会让上面三个节点内的值乘上自身
- 对于2,3是4和9,对于1还是1
- 这里 1 是一个没有变化的过程
- 按照正常逻辑来说,只需要更新原本值是 2 和 3 的节点
- 实际上 react 里面也是这样做的
- 参考demo如下
import React, { Component } from 'react' import './App.css'class List extends Component {state = {a: 1,b: 2,c: 3,}handleClick = () => {this.setState(oldState => {const { a, b, c } = oldStatereturn {a: a * a,b: b * b,c: c * c,}})}render() {const { a, b, c } = this.statereturn [<span key="a">{a}</span>,<span key="b">{b}</span>,<span key="c">{c}</span>,<button key="button" onClick={this.handleClick}>click me</button>,]} }class Input extends Component {state = {name: 'wang',}handleChange = e => {// 这里如果使用方法设置`state`// 那么需要现在外面读取`e.target.value`// 因为在React走完整个事件之后会重置event对象// 以复用event对象,如果等到方法被调用的时候再读取`e.target.value`// 那时`e.target`是`null`this.setState({name: e.target.value,})}render() {return (<inputtype="text"style={{ color: 'red' }}onChange={this.handleChange}value={this.state.name}/>)} }class App extends Component {render() {return (<div className="main"><Input /><List /></div>)} }export default App
- 这个时候我们在 浏览器中针对 react-dom.development.js 在 commitRoot 上面打了一个断点
- 这个断点是看最终要进行commit的时候,它是如何去获取哪几个节点是要更新的
- 也就是我们的 SideEffect 链是怎么样的一个形式, 点一下,断点被捕获,捕获了之后
- 可以看到它接收的两个参数,一个是root,一个是finishedWork,那么它们其实是一个对应的关系
- root.current.alternate 就等于 finishedWork
- 因为 finishedWork 对应的是 workInProgress
- finishedWork 上面就会记录我们当前这一次更新,它所有需要去执行的,就是要更新到dom上面的一些内容
- 它的记录就在 firstEffect 到 lastEffect 的一个链上
- 它这边 firstEffect 记录的 elementType 是一个 span
- 所谓 effect 它最终是一个fiber节点,就是告诉我们哪一个fiber节点需要更新
- 对于我们这边第二个span,它的值是要被更新成4的
- 所以可以看到它的 firstEffect 的第一个节点是 span
- 它的 effectTag是 4,然后它的 updateQueen 的属性里面是一个数组
updateQueue: ["children", "4"]
- 这个大致意思可以看出,我们要把这个span标签对应的dom节点, 它的children里面显示的文字内容,从2变成4
- 还有就是下一个节点, 也是一个span, 看 nextEffect, 它的 elementType 也是span
- 它的 updateQueen 是
updateQueue: ["children", "9"]
,也就是原值为 3 的节点
- 对于commitWork,只会关心 firstEffect 到 lastEffect 这个链条上面的对应的 fiber 节点
- 它只需要更新的就是这两个dom节点的children的一个变化
- 这就是react里面的 vdom,它以最小化的程度去更新 dom
- 而不需要对其他的任何节点再进行一个操作,以此来提升一个性能
- 这个过程, 就是在
v16.6.3/packages/react-reconciler/src/ReactFiberScheduler.js#L1026
这个 if 里面被实现的 - 这个 demo 示例对应最最上面的流程图来说
- 这边点了 button之后,在这里创建了一个update
- 就是这个List上面, 通过调用 this.setState 去创建了这个 update
- 最终是要从 RootFiber 上面往下进行一个更新,更新到 List 中的第一个span,以及后续的span
- 然后发现只有第2和第3个span,它们的 children从 2 变成了 4,从 3 变成了 9
- 它们两个对应的 SideEffect 是
Update
对应值为4 (二进制的表示形式, 参考 ReactSideEffectTags.js),它们要把内容挂载到dom上面 - 第一个span的内容因为是1乘以1,所以它没有变化,就不需要执行真正的更新
- 首先执行
completeUnitOfWork
的是 第一个 span, 接下去它的 sibling - 因为第一个 span 没有 SideEffect,在这里,它的 returnFiber 就是 List
- 当前的 workInProgress 就是这第一个 span,这个span没有任何的 SideEffect
- 这个 List 自己也没有 SideEffect,所以赋值List的时候,对List也是没有任何的一个更新的, 如下
if (returnFiber.firstEffect === null) {returnFiber.firstEffect = workInProgress.firstEffect; }
- 这时候的 List 本身的 firstEffect 到 lastEffect是没有任何内容的,也就是null
- 进行到第2个span节点,它自己有 SideEffect, 而它没有子节点
- 所以它本身上面的 firstEffect到lastEffect是没有任何内容的
- 唯一需要操作的是要把它作为List的第一个 SideEffect 增加到这个链上面
- 因为是
Update
, 值为 4 肯定是大于Performedwork
值为 1的if (effectTag > PerformedWork) {if (returnFiber.lastEffect !== null) {returnFiber.lastEffect.nextEffect = workInProgress; // 情况1,标记为 L1, 以便下面引用说明} else {returnFiber.firstEffect = workInProgress; // 情况2, 标记为 L2}returnFiber.lastEffect = workInProgress; // 通用设定3,标记为 L3 }
- 它自身(workInProgress)要作为 returnFiber 的第一个 SideEffect
- 给它增加到 List 的firstEffect到lastEffect的链上
- 所以returnFiber的 firstEffect 和 lastEffect,都等于这个Fiber对象(第二个span) workInProgress
- 对应的执行语句是
L2
和L3
- 当第2个span执行complete完了,又要开始它的sibling, 也就是第三个span
- 第三个span也是有更新的,所以它也要增加到 List上面
- 这个时候List上面已经有变化,因为List.lastEffect(姑且这样表示)已经不等于null了
- 这个时候,执行的是 else 的情况,即
L1
- 因为在上一个节点的complete过程当中,已经指定了 firstEffect 和 lastEffect 都为 workInProgress(第2个span)
- 所以第二个span节点的 nextEffect 指向的是第三个span的节点
- 它们更新完之后又要更新 button,因为它没有任何的变化,所以 button 也没有更新
- 这个时候对于List来说它的 SideEffect 链是等于 span指向span的这么一个过程
- List的firstEffect指向第二个span对应的Fiber对象,lastEffect指向第三个span对应的Fiber对象
- List本身执行
completeUnitOfWork
的时候,自己没有任何的更新 - 因为它的state更新对于真正的dom操作,没有任何的关系,而且它也没有生命周期方法
- 所以 List 后期没有任何要做的事情了, 自己本身是没有 SideEffect,只有子节点的 SideEffect
- 在 List 执行
completeUnitOfWork
的时候, 代码中的 returnFiber 对应是 div - 而 workInProgress 对应的是 List, 而 List 要赋值它的 firstEffect 和 lastEffect
- 它的链指向returnFiber, 就是要放到 returnFiber 它的链的最后面
- returnFiber 这个 div,它目前是肯定没有任何的 SideEffect的, 所以它直接赋值成 workInProgress.firstEffect
- 也就是说,对于 div 它的 firstEffect 跟 lastEffect 已经变成 List 的 firstEffect 跟 lastEffect
- 因为上面节点都是没有任何更新的, 所以一层一层往上之后, 在
RootFiber
上面记录的 - firstEffect 跟 lastEffect 也就变成了最开始的两个span
- 所以这就是通过
completeUnitOfWork
,最终能够赋值到RootFiber
上面 - 在它的 firstEffect 到 lastEffect,单项链表上面去记录整个应用当中
- 所有需要去更新的最终的dom节点以及组件的fiber对象的一个过程
- 这里涉及到后期 commitRoot 的时候, 调用这个单项链表一个过程,这里先跳过
- 对于 unwindWork 的一个过程, 也是相似的, 先跳过 unwindWork 以及 completeWork
- 目前只关心它的一个遍历过程,跳过具体节点做的事情, 关注它的大致流程
- 它真正帮我们去实现了把所有需要更新的节点进行一个串联
- 让最终 commitRoot 的时候,能够方便获取到所有需要更新的节点的一个过程
相关文章:

React16源码: React中的completeUnitOfWork的源码实现
completeUnitOfWork 1 )概述 各种不同类型组件的一个更新过程对应的是在执行 performUnitOfWork 里面的 beginWork 阶段它是去向下遍历一棵 fiber 树的一侧的子节点,然后遍历到叶子节点为止,以及 return 自己 child 的这种方式在 performUni…...

uniapp移动端——企业微信H5调用jssdk实现扫一扫,通过weixin-java-cp获取ticket签名,配置config
背景: 使用企业微信开发扫一扫功能 可信域名验证 (1)企业微信的可信域名需要和企业微信的备案主体一致。 域名备案主体可通过站长工具查看域名备案主体。https://icp.chinaz.com/ 企业微信备案主体可以咨询管理员 (2)通过nginx配置域名归…...

【前端基础--1】
为后面爬虫打基础 使用Visual Studio Code(VS Code) https://code.visualstudio.com/#alt-downloads 网页基础 创建一个html网页 新建一个文件 文件名后缀.html 书写网页模板 html:5 回车键(或者Tab键)英文感叹号! 回…...

E2 Mysql的基本操作和用户权限
一、实验目的: 要求掌握Mysql平台的基本操作和基本的权限管理。 二、实验要求: 1、基本硬件配置:英特尔Pentium III 以上,大于4G内存; 2、软件要求:Mysql; 3、时间:4小时; 4、撰写实验报告并按时提交。 三、实验内容: Group 1: 安装Mys…...

TCP 的三次握手和四次挥手
Java 面试题 TCP 三次握手 第一次握手:客户端向服务端发送SYN包。报文中标志位SYN1,序列号seqx(x为随机整数)。此时客户端进入了 SYN_SEND 同步已发送状态。 第二次握手:服务端回复客户端SYNACK包。报文中标志位SYN1&…...

mybatisplus做SQL拦截添加自定义排序
前言 工作中写的一段代码,备个份,以后兴许能直接用 功能描述:如果前端传入了排序规则,则优先按传入的字段进行排序,SQL原有的排序规则追加到末尾 注:我们项目里的分页查询,是基于XML的SQL执行的…...

代码随想录算法训练营第29天(回溯算法05 | * 491.递增子序列 * 46.全排列 * 47.全排列 II
回溯算法part05 491.递增子序列解题思路与 90.子集II 不同的点回溯三部曲 46.全排列解题思路遇到的难点思考 47.全排列 II解题思路注意点拓展需要加深理解的点(需复习 小总结 491.递增子序列 本题和大家刚做过的90.子集II非常像,但又很不一样,…...

mac docker desktop被禁用了,如何使用虚拟机lima运行docker
安装lima brew install lima创建配置 echo "\\ndynamic:\n big-sur:\n image: docker://docker:git\n linux:\n image: docker.io/limasoftware/ubuntu:20.04 \\n" > ~/.lima/default.yaml启动名叫default的虚拟机 limactl start default测试 limactl …...

sublime text 开启vim模式
sublime text 开启vim模式 打开配置文件 mac下点击菜单栏 Sublime Text -> Settings... -> Settings 修改配置文件并保存 添加配置 // 开启vim模式 "ignored_packages": [// "Vintage", ], // 以命令模式打开文件 "vintage_start_in_comman…...

JS词法结构
编程语言的词法结构是一套基础性规则,用来描述如何使用这门语言来编写程序。作为语法的基础,它规定了诸如变量名是什么样的、怎么写注释,以及程序语句之间如何分隔等规则。 2.1程序的文本 JS区分大小写 JS忽略程序记号(token&am…...

程序媛的mac修炼手册-- 如何用Python节省WPS会员费
上篇分享了如何用微博爬虫,咱举例爬了女明星江疏影的微博数据。今天就用这些数据,给大家安利一下怎么用Python实现WPS中部分Excel付费功能。 MacOS系统自带的工具,绝大多数都非常顶,除Numbers外。当然,page比起word来&…...

ASP.NET Core NE8实现HTTP Upgrade和HTTP CONNECT代理服务器
看到一个文章[Go] 不到 100 行代码实现一个支持 CONNECT 动词的 HTTP 服务器 在NET8中如何实现 创建项目为MiniApi 编辑Program.cs文件。 var builder WebApplication.CreateSlimBuilder(args);var app builder.Build();// 将HTTP请求通过协议升级机制转为远程TCP请求&…...

apipost和curl收不到服务器响应的HTTP/1.1 404 Not Found
windows的apipost发送请求后,服务器响应了HTTP/1.1 404 Not Found,但是apipost一直显示发送中。 linux上的curl也一样。 使用wireshark抓包发现收到了响应,但是wireshark识别不了(图中是回应404后关闭了连接)ÿ…...

javascript:计算一个坐标数组的最小值点、最大值点、中心点
作者:CSDN _乐多_ 本文将介绍使用 javascript 语言计算一个坐标数组的最小值点、最大值点、中心点的代码。 文章目录 一、代码 一、代码 function calculateCenterPoint(points) {if (points.length 0) {return null;}let sumX 0;let sumY 0;let sumZ 0;for …...

使用远程工具连接Linux系统——使用Root用户登录
1、启动虚拟机,输入以下命令 进入root用户 sudo su或 su root修改ssh配置文件 vim /etc/ssh/sshd_config找到PermitRootLogin 并用#注释掉当前行 # PermitRootLogin prohibit-password添加: PermitRootLogin yes键入esc输入:wq保存退出 2、重启服…...

JuiceSSH结合内网穿透实现移动端设备公网远程访问Linux虚拟机
文章目录 1. Linux安装cpolar2. 创建公网SSH连接地址3. JuiceSSH公网远程连接4. 固定连接SSH公网地址5. SSH固定地址连接测试 处于内网的虚拟机如何被外网访问呢?如何手机就能访问虚拟机呢? cpolarJuiceSSH 实现手机端远程连接Linux虚拟机(内网穿透,手机端连接Linux虚拟机) …...

06-枚举和模式匹配
上一篇:05-使用结构体构建相关数据 在本章中,我们将介绍枚举。枚举允许你通过枚举其可能的变体来定义一种类型。首先,我们将定义并使用一个枚举,以展示枚举如何与数据一起编码意义。接下来,我们将探索一个特别有用的枚…...

【C/C++】C/C++编程——C++ 开发环境搭建
C的开发环境种类繁多,以下是一些常见的C 集成开发环境: AppCode :构建与JetBrains’ IntelliJ IDEA 平台上的用于Objective-C,C,C,Java和Java开发的集成开发环境CLion:来自JetBrains的跨平台的C/C的集成开…...

Go 接口
接口概览 接口大概理解 接口类型是队其他类型行为的概括与抽象 接口类型中,包含函数声明,但没有数据变量接口的作用通过使用接口,可以写出更加灵活和通用的函数,这些函数不用绑定在一个特定的类型实现上Go 接口特征 很多面向对象…...

用 AI 将自拍照 P 进不同艺术作品,谷歌发布「艺术自拍 2」
1 月 24 日消息,谷歌旗下「艺术与文化」应用今日宣布,2018 年推出的「艺术自拍」功能在时隔近六年后,借助生成式 AI 的力量回归。官方表示,「艺术自拍 2」将再次使用户与艺术面对面,重新探访世界各地的艺术、历史和文化…...

SpringSecurity+OAuth2.0 搭建认证中心和资源服务中心
目录 1. OAuth2.0 简介 2. 代码搭建 2.1 认证中心(8080端口) 2.2 资源服务中心(8081端口) 3. 测试结果 1. OAuth2.0 简介 OAuth 2.0(开放授权 2.0)是一个开放标准,用于授权第三方应用程序…...

c# 策略模式
在 C# 中,策略模式是一种行为型设计模式,它定义了一系列算法,并将每个算法封装到具有公共接口的独立类中,使得它们可以互相替换。这样可以使得算法的选择独立于算法的使用者,从而提高了灵活性和可维护性。 以下是策略…...

消息队列RabbitMQ.03.死信交换机的讲解与使用
目录 一、死信队列(延迟队列) 概念讲解 二、确认消息(局部方法处理消息) 三、代码实战 1.编写生产者代码,配置消息、直连交换机、路由键 1.1代码解析: 2.配置消费者接受类接受直连交换机的路由键 2.1. String msgÿ…...

人工智能原理实验4(2)——贝叶斯、决策求解汽车评估数据集
🧡🧡实验内容🧡🧡 汽车数据集 车子具有 buying,maint,doors,persons,lug_boot and safety六种属性,而车子的好坏分为uncc,ucc,good and vgood四种。 🧡🧡贝叶斯求解🧡🧡…...

算力网络:未来计算资源的驱动力
文章目录 前言一、算力网络的基本概况(一)算力网络的基本概念(二)算力网络研究进展二、运营商的算力网络架构(一)算力网络基础设施构成(二)算力网络编排管理(三)能力开放三、算力网络的优势(一)弹性计算(二)降低成本(三)去中心化四、算力网络的应用场景(一)人…...

java动态导入excel按照表头生成数据库表
1、创建接口接收文件 //controller层 PostMapping("/importExcel1")public void importExcel1(HttpServletRequest request, MultipartFile file) {try {waterMeterService.importExcel1(request,file);} catch (Exception e) {throw new RuntimeException(e);}}//se…...

Java 集合List相关面试题
📕作者简介: 过去日记,致力于Java、GoLang,Rust等多种编程语言,热爱技术,喜欢游戏的博主。 📗本文收录于java面试题系列,大家有兴趣的可以看一看 📘相关专栏Rust初阶教程、go语言基…...

k8s-基础知识(Pod,Deployment,ReplicaSet)
k8s职责 自动化容器部署和复制随时扩展或收缩容器容器分组group,并且提供容器间的负载均衡实时监控,即时故障发现,自动替换 k8s概念及架构 pod pod是容器的容器,可以包含多个container pod是k8s最小可部署单元,容器…...

matlab查看源代码
matlab函数源代码-查看 CtrlD 最简单方便的一种方法,鼠标划中函数名,按CTRLD即可打开函数的m文件...

【数据库学习】PostgreSQL优化
1,思路 2,执行计划 explain sql语句; #查看执行计划。也可以使用navicat的解释功能查看。结果说明: QUERY PLAN Index Scan using tenk1_unique1 on tenk1 (cost0.00..10.01 rows1 width244) --Index 使用索引 --cost&#x…...