React16源码: React中的updateClassComponent的源码实现

本文主要是介绍React16源码: React中的updateClassComponent的源码实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ClassComponent 的更新


1 ) 概述

  • 在 react 中 class component,是一个非常重要的角色
  • 它承担了 react 中 更新整个应用的API
    • setState
    • forceUpdate
  • 在react当中,只有更新了state之后,整个应用才会重新进行渲染
  • 在 class component 中, 它的逻辑相对复杂

2 )源码

在 packages/react-reconciler/src/ReactFiberBeginWork.js

// 这个方法就是更新 ClassComponent 组件的一个过程
function updateClassComponent(current: Fiber | null,workInProgress: Fiber,Component: any,nextProps,renderExpirationTime: ExpirationTime,
) {// Push context providers early to prevent context stack mismatches.// During mounting we don't know the child context yet as the instance doesn't exist.// We will invalidate the child context in finishClassComponent() right after rendering.// 先跳过 context 相关的逻辑let hasContext;if (isLegacyContextProvider(Component)) {hasContext = true;pushLegacyContextProvider(workInProgress);} else {hasContext = false;}prepareToReadContext(workInProgress, renderExpirationTime);// instance 就是我们 class component,通过new这个class获取的一个对象const instance = workInProgress.stateNode;// 在这里面,它声明了一个 shouldUpdate 的一个属性let shouldUpdate; // 先判断instance是否存在, 比如说我们第一次通过 ReactDOM.render 进行渲染的过程当中// 在从上往下第一次渲染的过程当中,第一次更新到 class component 的时候// 它的instance肯定是不存在的,因为它还没有被更新过,所以它的节点肯定是没有被创建的if (instance === null) {// 接下去, 判断一下current是否等于null// current等于null的情况是代表在进入第一次渲染,因为current它还不存在// 如果current不等于null, 代表我们至少已经经历过一次渲染了// 这时候 instance 不存在,而 current 存在,说明第一次渲染的时候没有创建这个instance// 同样说明这个组件是被 suspended 的,一个组件处于suspended的状态// 在这里react认为它相当于是第一次被渲染, 在初次渲染的时候,只是抛出了一个promise// 并没有真正的渲染出它的子节点, 抛出了一个promise之后,接下去的渲染就结束了if (current !== null) {// An class component without an instance only mounts if it suspended// inside a non- concurrent tree, in an inconsistent state. We want to// tree it like a new mount, even though an empty version of it already// committed. Disconnect the alternate pointers.current.alternate = null;workInProgress.alternate = null;// Since this is conceptually a new fiber, schedule a Placement effectworkInProgress.effectTag |= Placement;}// In the initial pass we might need to construct the instance.// 对于没有instance的一个情况,需要去创建 class instanceconstructClassInstance(workInProgress,Component,nextProps,renderExpirationTime,);// 并且要mount这个 class instancemountClassInstance(workInProgress,Component,nextProps,renderExpirationTime,);// 在第一次渲染的时候,会执行上述两个方法,并且 shouldUpdate = true;shouldUpdate = true;} else if (current === null) {// In a resume, we'll already have an instance we can reuse.// 在 有instance 和 没有 current 的情况下,这种是之前被中断的// 在执行 class component 的 render 方法的时候 报错,但 instance 已被创建// 代表着可以复用 instanceshouldUpdate = resumeMountClassInstance(workInProgress,Component,nextProps,renderExpirationTime,);} else {// 对于又有 current 又有 instance的情况,说明组件已经被重新渲染了// 这个 updateClassInstance 方法和 上述 resumeMountClassInstance 类似// 最大的区别是 内部判断 comonentDidUpdate shouldUpdate = updateClassInstance(current,workInProgress,Component,nextProps,renderExpirationTime,);}// 这里最终调用 finishClassComponentreturn finishClassComponent(current,workInProgress,Component,shouldUpdate,hasContext,renderExpirationTime,);
}
  • 进入 constructClassInstance

    function constructClassInstance(workInProgress: Fiber,ctor: any,props: any,renderExpirationTime: ExpirationTime,
    ): any {// 先跳过 context 相关let isLegacyContextConsumer = false;let unmaskedContext = emptyContextObject;let context = null;const contextType = ctor.contextType;// if (typeof contextType === 'object' && contextType !== null) {// 跳过 DEVif (__DEV__) {if (contextType.$$typeof !== REACT_CONTEXT_TYPE &&!didWarnAboutInvalidateContextType.has(ctor)) {didWarnAboutInvalidateContextType.add(ctor);warningWithoutStack(false,'%s defines an invalid contextType. ' +'contextType should point to the Context object returned by React.createContext(). ' +'Did you accidentally pass the Context.Provider instead?',getComponentName(ctor) || 'Component',);}}context = readContext((contextType: any));} else {unmaskedContext = getUnmaskedContext(workInProgress, ctor, true);const contextTypes = ctor.contextTypes;isLegacyContextConsumer =contextTypes !== null && contextTypes !== undefined;context = isLegacyContextConsumer? getMaskedContext(workInProgress, unmaskedContext): emptyContextObject;}// Instantiate twice to help detect side-effects.if (__DEV__) {if (debugRenderPhaseSideEffects ||(debugRenderPhaseSideEffectsForStrictMode &&workInProgress.mode & StrictMode)) {new ctor(props, context); // eslint-disable-line no-new}}// ctor 是 construct 的一个缩写 这个 ctor 就是在 ReactElement当中// 存在的那个type,也就是 class component 定义的那个class// 传入 props和context,对应于 ReactBaseClasses.js 里面,Component 函数 接收的这两个参数// 第三个参数 updater 后面在 adoptClassInstance 里面设置const instance = new ctor(props, context);// 获取 stateconst state = (workInProgress.memoizedState =instance.state !== null && instance.state !== undefined? instance.state: null);adoptClassInstance(workInProgress, instance);if (__DEV__) {if (typeof ctor.getDerivedStateFromProps === 'function' && state === null) {const componentName = getComponentName(ctor) || 'Component';if (!didWarnAboutUninitializedState.has(componentName)) {didWarnAboutUninitializedState.add(componentName);warningWithoutStack(false,'`%s` uses `getDerivedStateFromProps` but its initial state is ' +'%s. This is not recommended. Instead, define the initial state by ' +'assigning an object to `this.state` in the constructor of `%s`. ' +'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.',componentName,instance.state === null ? 'null' : 'undefined',componentName,);}}// If new component APIs are defined, "unsafe" lifecycles won't be called.// Warn about these lifecycles if they are present.// Don't warn about react-lifecycles-compat polyfilled methods though.if (typeof ctor.getDerivedStateFromProps === 'function' ||typeof instance.getSnapshotBeforeUpdate === 'function') {let foundWillMountName = null;let foundWillReceivePropsName = null;let foundWillUpdateName = null;if (typeof instance.componentWillMount === 'function' &&instance.componentWillMount.__suppressDeprecationWarning !== true) {foundWillMountName = 'componentWillMount';} else if (typeof instance.UNSAFE_componentWillMount === 'function') {foundWillMountName = 'UNSAFE_componentWillMount';}if (typeof instance.componentWillReceiveProps === 'function' &&instance.componentWillReceiveProps.__suppressDeprecationWarning !== true) {foundWillReceivePropsName = 'componentWillReceiveProps';} else if (typeof instance.UNSAFE_componentWillReceiveProps === 'function') {foundWillReceivePropsName = 'UNSAFE_componentWillReceiveProps';}if (typeof instance.componentWillUpdate === 'function' &&instance.componentWillUpdate.__suppressDeprecationWarning !== true) {foundWillUpdateName = 'componentWillUpdate';} else if (typeof instance.UNSAFE_componentWillUpdate === 'function') {foundWillUpdateName = 'UNSAFE_componentWillUpdate';}if (foundWillMountName !== null ||foundWillReceivePropsName !== null ||foundWillUpdateName !== null) {const componentName = getComponentName(ctor) || 'Component';const newApiName =typeof ctor.getDerivedStateFromProps === 'function'? 'getDerivedStateFromProps()': 'getSnapshotBeforeUpdate()';if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(componentName)) {didWarnAboutLegacyLifecyclesAndDerivedState.add(componentName);warningWithoutStack(false,'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +'%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n' +'The above lifecycles should be removed. Learn more about this warning here:\n' +'https://fb.me/react-async-component-lifecycle-hooks',componentName,newApiName,foundWillMountName !== null ? `\n  ${foundWillMountName}` : '',foundWillReceivePropsName !== null? `\n  ${foundWillReceivePropsName}`: '',foundWillUpdateName !== null ? `\n  ${foundWillUpdateName}` : '',);}}}}// Cache unmasked context so we can avoid recreating masked context unless necessary.// ReactFiberContext usually updates this cache but can't for newly-created instances.if (isLegacyContextConsumer) {cacheContext(workInProgress, unmaskedContext, context);}return instance;
    }
    
    • 进入 adoptClassInstance
      function adoptClassInstance(workInProgress: Fiber, instance: any): void {instance.updater = classComponentUpdater; // 挂载 update 方法workInProgress.stateNode = instance; // instance 挂载到 stateNode 以供下次进来时使用,下次进来就会存在了// The instance needs access to the fiber so that it can schedule updatesReactInstanceMap.set(instance, workInProgress);if (__DEV__) {instance._reactInternalInstance = fakeInternalInstance;}
      }
      
    • 进入 ReactInstanceMap 这个就是对 instance 上 _reactInternalFiber 属性的设置
      export function remove(key) {key._reactInternalFiber = undefined;
      }export function get(key) {return key._reactInternalFiber;
      }export function has(key) {return key._reactInternalFiber !== undefined;
      }export function set(key, value) {key._reactInternalFiber = value;
      }
      
      • 这也意味着,通过 this._reactInternalFiber 就可以拿到当前 fiber 对象
  • 进入 mountClassInstance

    // Invokes the mount life-cycles on a previously never rendered instance.
    function mountClassInstance(workInProgress: Fiber,ctor: any,newProps: any,renderExpirationTime: ExpirationTime,
    ): void {if (__DEV__) {checkClassInstance(workInProgress, ctor, newProps);}const instance = workInProgress.stateNode;instance.props = newProps;instance.state = workInProgress.memoizedState;instance.refs = emptyRefsObject;const contextType = ctor.contextType;if (typeof contextType === 'object' && contextType !== null) {instance.context = readContext(contextType);} else {const unmaskedContext = getUnmaskedContext(workInProgress, ctor, true);instance.context = getMaskedContext(workInProgress, unmaskedContext);}if (__DEV__) {if (instance.state === newProps) {const componentName = getComponentName(ctor) || 'Component';if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) {didWarnAboutDirectlyAssigningPropsToState.add(componentName);warningWithoutStack(false,'%s: It is not recommended to assign props directly to state ' +"because updates to props won't be reflected in state. " +'In most cases, it is better to use props directly.',componentName,);}}if (workInProgress.mode & StrictMode) {ReactStrictModeWarnings.recordUnsafeLifecycleWarnings(workInProgress,instance,);ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress,instance,);}if (warnAboutDeprecatedLifecycles) {ReactStrictModeWarnings.recordDeprecationWarnings(workInProgress,instance,);}}// 获取 updateQueue,初次渲染这个 updateQueue 是空的// 对于有 setState 的情况,它的 updateQueen 里面可能有多个update// 这个时候, 需要调用这个 updateQueen 来去得到一个新的statelet updateQueue = workInProgress.updateQueue;if (updateQueue !== null) {// 这里 计算出新的state 并赋值给 workInProgress.memoizedStateprocessUpdateQueue(workInProgress,updateQueue,newProps,instance,renderExpirationTime,);// 同时更新 instance.stateinstance.state = workInProgress.memoizedState;}// 判断是否有这个生命周期方法const getDerivedStateFromProps = ctor.getDerivedStateFromProps;if (typeof getDerivedStateFromProps === 'function') {// 如果存在该生命周期方法,则计算新的state// 这个生命周期会在组件更新的过程中被调用applyDerivedStateFromProps(workInProgress,ctor,getDerivedStateFromProps,newProps,);instance.state = workInProgress.memoizedState;}// In order to support react-lifecycles-compat polyfilled components,// Unsafe lifecycles should not be invoked for components using the new APIs.// 判断是否有 componentWillMount 生命周期方法// 在这个生命周期方法中,会执行 setState 方法if (typeof ctor.getDerivedStateFromProps !== 'function' &&typeof instance.getSnapshotBeforeUpdate !== 'function' &&(typeof instance.UNSAFE_componentWillMount === 'function' ||typeof instance.componentWillMount === 'function')) {// callComponentWillMount(workInProgress, instance);// If we had additional state updates during this life-cycle, let's// process them now.// 执行了 这个生命周期方法,就需要重新执行 updateQueue// 如果在这时执行了 setState, 立马被反映到组件上面updateQueue = workInProgress.updateQueue;if (updateQueue !== null) {processUpdateQueue(workInProgress,updateQueue,newProps,instance,renderExpirationTime,);instance.state = workInProgress.memoizedState;}}if (typeof instance.componentDidMount === 'function') {workInProgress.effectTag |= Update;}
    }
    
    • 进入 processUpdateQueue
      export function processUpdateQueue<State>(workInProgress: Fiber,queue: UpdateQueue<State>,props: any,instance: any,renderExpirationTime: ExpirationTime,
      ): void {hasForceUpdate = false;// 克隆 updateQueuequeue = ensureWorkInProgressQueueIsAClone(workInProgress, queue);if (__DEV__) {currentlyProcessingQueue = queue;}// These values may change as we process the queue.let newBaseState = queue.baseState;let newFirstUpdate = null;let newExpirationTime = NoWork;// Iterate through the list of updates to compute the result.let update = queue.firstUpdate; let resultState = newBaseState;while (update !== null) {const updateExpirationTime = update.expirationTime;if (updateExpirationTime < renderExpirationTime) {// This update does not have sufficient priority. Skip it.if (newFirstUpdate === null) {// This is the first skipped update. It will be the first update in// the new list.newFirstUpdate = update;// Since this is the first update that was skipped, the current result// is the new base state.newBaseState = resultState;}// Since this update will remain in the list, update the remaining// expiration time.if (newExpirationTime < updateExpirationTime) {newExpirationTime = updateExpirationTime;}} else {// This update does have sufficient priority. Process it and compute// a new result.resultState = getStateFromUpdate(workInProgress,queue,update,resultState,props,instance,);const callback = update.callback;// 判断是否有 callbackif (callback !== null) {workInProgress.effectTag |= Callback; // 加上 Callback 这块// Set this to null, in case it was mutated during an aborted render.update.nextEffect = null; // 防止在中断的渲染中被修改if (queue.lastEffect === null) {queue.firstEffect = queue.lastEffect = update; // 链表操作} else {queue.lastEffect.nextEffect = update;queue.lastEffect = update;}}}// Continue to the next update.update = update.next;}// Separately, iterate though the list of captured updates.let newFirstCapturedUpdate = null;update = queue.firstCapturedUpdate;while (update !== null) {const updateExpirationTime = update.expirationTime;if (updateExpirationTime < renderExpirationTime) {// This update does not have sufficient priority. Skip it.if (newFirstCapturedUpdate === null) {// This is the first skipped captured update. It will be the first// update in the new list.newFirstCapturedUpdate = update;// If this is the first update that was skipped, the current result is// the new base state.if (newFirstUpdate === null) {newBaseState = resultState;}}// Since this update will remain in the list, update the remaining// expiration time.if (newExpirationTime < updateExpirationTime) {newExpirationTime = updateExpirationTime;}} else {// This update does have sufficient priority. Process it and compute// a new result.resultState = getStateFromUpdate(workInProgress,queue,update,resultState,props,instance,);const callback = update.callback;if (callback !== null) {workInProgress.effectTag |= Callback;// Set this to null, in case it was mutated during an aborted render.update.nextEffect = null;if (queue.lastCapturedEffect === null) {queue.firstCapturedEffect = queue.lastCapturedEffect = update;} else {queue.lastCapturedEffect.nextEffect = update;queue.lastCapturedEffect = update;}}}update = update.next;}if (newFirstUpdate === null) {queue.lastUpdate = null;}if (newFirstCapturedUpdate === null) {queue.lastCapturedUpdate = null;} else {workInProgress.effectTag |= Callback;}if (newFirstUpdate === null && newFirstCapturedUpdate === null) {// We processed every update, without skipping. That means the new base// state is the same as the result state.newBaseState = resultState;}queue.baseState = newBaseState;queue.firstUpdate = newFirstUpdate;queue.firstCapturedUpdate = newFirstCapturedUpdate;// Set the remaining expiration time to be whatever is remaining in the queue.// This should be fine because the only two other things that contribute to// expiration time are props and context. We're already in the middle of the// begin phase by the time we start processing the queue, so we've already// dealt with the props. Context in components that specify// shouldComponentUpdate is tricky; but we'll have to account for// that regardless.workInProgress.expirationTime = newExpirationTime;workInProgress.memoizedState = resultState;if (__DEV__) {currentlyProcessingQueue = null;}
      }
      
      • 进入 ensureWorkInProgressQueueIsAClone
      function ensureWorkInProgressQueueIsAClone<State>(workInProgress: Fiber,queue: UpdateQueue<State>,
      ): UpdateQueue<State> {const current = workInProgress.alternate;if (current !== null) {// If the work-in-progress queue is equal to the current queue,// we need to clone it first.if (queue === current.updateQueue) {// 要保证 workInProgress.updateQueue 是一个克隆的queue, 而非直接进行修改queue = workInProgress.updateQueue = cloneUpdateQueue(queue); // 拷贝 queue}}return queue;
      }
      
    • 进入 getStateFromUpdate
      function getStateFromUpdate<State>(workInProgress: Fiber,queue: UpdateQueue<State>,update: Update<State>,prevState: State,nextProps: any,instance: any,
      ): any {switch (update.tag) {case ReplaceState: {const payload = update.payload;if (typeof payload === 'function') {// Updater functionif (__DEV__) {if (debugRenderPhaseSideEffects ||(debugRenderPhaseSideEffectsForStrictMode &&workInProgress.mode & StrictMode)) {payload.call(instance, prevState, nextProps);}}return payload.call(instance, prevState, nextProps);}// State objectreturn payload;}// 这里 a & ~b 表示: a & 除了b之外的所有属性case CaptureUpdate: {workInProgress.effectTag =(workInProgress.effectTag & ~ShouldCapture) | DidCapture; // 这里最终剩下的 只有 DidCapture}// Intentional fallthroughcase UpdateState: {const payload = update.payload;let partialState;if (typeof payload === 'function') {// Updater functionif (__DEV__) {if (debugRenderPhaseSideEffects ||(debugRenderPhaseSideEffectsForStrictMode &&workInProgress.mode & StrictMode)) {payload.call(instance, prevState, nextProps);}}// 如果是 function 则调用 payload 传入之前的参数 计算出 statepartialState = payload.call(instance, prevState, nextProps);} else {// Partial state objectpartialState = payload;}// 处理特殊情况if (partialState === null || partialState === undefined) {// Null and undefined are treated as no-ops.return prevState;}// Merge the partial state and the previous state.// 合并return Object.assign({}, prevState, partialState);}case ForceUpdate: {hasForceUpdate = true;return prevState;}}return prevState;
      }
      
  • 进入 finishClassComponent

    function finishClassComponent(current: Fiber | null,workInProgress: Fiber,Component: any,shouldUpdate: boolean,hasContext: boolean,renderExpirationTime: ExpirationTime,
    ) {// Refs should update even if shouldComponentUpdate returns false// 这个先跳过markRef(current, workInProgress);// 判断 workInProgress.effectTag 上是否有 DidCaptureconst didCaptureError = (workInProgress.effectTag & DidCapture) !== NoEffect;// 在没有更新也没有错误捕获的情况下if (!shouldUpdate && !didCaptureError) {// Context providers should defer to sCU for renderingif (hasContext) {invalidateContextProvider(workInProgress, Component, false);}// 跳过更新return bailoutOnAlreadyFinishedWork(current,workInProgress,renderExpirationTime,);}const instance = workInProgress.stateNode;// RerenderReactCurrentOwner.current = workInProgress;let nextChildren;// 有任何错误捕获, 但没有配置这个api的时候// 这个 getDerivedStateFromError 生命周期的api和 componentDidCatch 有区别, 后者在下次更新的时候处理,中间可能instance不存在(因为出错了)// 就继续可能引发在这个class component上面设置的 ref拿到一个null, 操作ref的时候就会出现错误// 在前者这个新的生命周期的api中, 在本次渲染中,生成 state, 渲染出属性, 这样对于 instance 对象依然存在 对应 ref 就可以拿到实际的对象if (didCaptureError &&typeof Component.getDerivedStateFromError !== 'function') {// If we captured an error, but getDerivedStateFrom catch is not defined,// unmount all the children. componentDidCatch will schedule an update to// re-render a fallback. This is temporary until we migrate everyone to// the new API.// TODO: Warn in a future release.nextChildren = null;if (enableProfilerTimer) {stopProfilerTimerIfRunning(workInProgress);}} else {if (__DEV__) {ReactCurrentFiber.setCurrentPhase('render');nextChildren = instance.render();if (debugRenderPhaseSideEffects ||(debugRenderPhaseSideEffectsForStrictMode &&workInProgress.mode & StrictMode)) {instance.render();}ReactCurrentFiber.setCurrentPhase(null);} else {// 调用 render 方法,计算出新的 childrennextChildren = instance.render();}}// React DevTools reads this flag.workInProgress.effectTag |= PerformedWork; // 增加 PerformedWork// 不是第一次渲染,并且有错误捕获if (current !== null && didCaptureError) {// If we're recovering from an error, reconcile without reusing any of// the existing children. Conceptually, the normal children and the children// that are shown on error are two different sets, so we shouldn't reuse// normal children even if their identities match.forceUnmountCurrentAndReconcile(current,workInProgress,nextChildren,renderExpirationTime,);} else {// 正常情况调用 调和 childrenreconcileChildren(current,workInProgress,nextChildren,renderExpirationTime,);}// Memoize state using the values we just used to render.// TODO: Restructure so we never read values from the instance.workInProgress.memoizedState = instance.state;// The context might have changed so we need to recalculate it.if (hasContext) {invalidateContextProvider(workInProgress, Component, true);}return workInProgress.child; // 把 render 方法渲染出来的第一个子节点 返回给 nextUnitOfWork, 就可以在 workLoop 中继续进行更新的流程
    }
    
  • 简单总结

    • 以上是更新 class component 的整体流程
    • 一开始要使用 constructClassInstance 创建 class instance
    • 内部会根据不同情况调用不同方法
    • 并且要调用 mountClassInstance 来挂载
    • 如果是第一次渲染被中断的情况
      • 如果存在 instance 则重复使用 instance
      • 它调用的生命周期方法仍然是 第一次渲染的生命周期方法
      • 也就是 componentDidMount
    • 如果不是第一次渲染的情况
      • 调用 updateClassInstance 方法
      • 这种会最终调用 componentDidUpdate 方法
    • 它们中间的流程类似
      • 判断各种情况,创建新的 instance 或 复用之前的
      • 通过 processUpdateQueue 来获取新的 state
      • 会把它赋值到 instance 和 fiber 上面进行记录
      • 最终都会调用 finishClassComponent
        • 这里面做一些错误判断的处理
        • 以及是否可以跳过更新的过程
        • 还有重新调和子节点 (通用流程)

这篇关于React16源码: React中的updateClassComponent的源码实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/629482

相关文章

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

Python中pywin32 常用窗口操作的实现

《Python中pywin32常用窗口操作的实现》本文主要介绍了Python中pywin32常用窗口操作的实现,pywin32主要的作用是供Python开发者快速调用WindowsAPI的一个... 目录获取窗口句柄获取最前端窗口句柄获取指定坐标处的窗口根据窗口的完整标题匹配获取句柄根据窗口的类别匹配获取句

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

Python位移操作和位运算的实现示例

《Python位移操作和位运算的实现示例》本文主要介绍了Python位移操作和位运算的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 位移操作1.1 左移操作 (<<)1.2 右移操作 (>>)注意事项:2. 位运算2.1

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

SpringMVC 通过ajax 前后端数据交互的实现方法

《SpringMVC通过ajax前后端数据交互的实现方法》:本文主要介绍SpringMVC通过ajax前后端数据交互的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价... 在前端的开发过程中,经常在html页面通过AJAX进行前后端数据的交互,SpringMVC的controll

Spring Security自定义身份认证的实现方法

《SpringSecurity自定义身份认证的实现方法》:本文主要介绍SpringSecurity自定义身份认证的实现方法,下面对SpringSecurity的这三种自定义身份认证进行详细讲解,... 目录1.内存身份认证(1)创建配置类(2)验证内存身份认证2.JDBC身份认证(1)数据准备 (2)配置依

利用python实现对excel文件进行加密

《利用python实现对excel文件进行加密》由于文件内容的私密性,需要对Excel文件进行加密,保护文件以免给第三方看到,本文将以Python语言为例,和大家讲讲如何对Excel文件进行加密,感兴... 目录前言方法一:使用pywin32库(仅限Windows)方法二:使用msoffcrypto-too