湖南高端网站制作公司/武汉seo优化

湖南高端网站制作公司,武汉seo优化,360如何做网站优化,php语言开发网站流程useId的介绍 https://zh-hans.react.dev/reference/react/useId useId 是 React 18 引入的一个新 Hook,主要用于生成全局唯一的 ID。在开发中,我们经常需要为元素(如表单元素、模态框等)生成唯一 ID,以便在 JavaScri…

useId的介绍

https://zh-hans.react.dev/reference/react/useId

useId 是 React 18 引入的一个新 Hook,主要用于生成全局唯一的 ID。在开发中,我们经常需要为元素(如表单元素、模态框等)生成唯一 ID,以便在 JavaScript 中进行操作或在 CSS 中进行样式绑定。使用 useId 可以避免手动管理 ID 带来的问题,比如在服务器端渲染(SSR)时客户端和服务器端生成的 ID 不一致。

useId的使用

例子:基本用法

import React, { useId } from 'react';function App() {const id = useId();return (<div><label htmlFor={id}>用户名:</label><input type="text" id={id} /></div>);
}export default App;

例子:处理多个ID

import React, { useId } from 'react';function App() {const baseId = useId();const nameId = `${baseId}-name`;const emailId = `${baseId}-email`;return (<form><label htmlFor={nameId}>姓名:</label><input type="text" id={nameId} /><br /><label htmlFor={emailId}>邮箱:</label><input type="email" id={emailId} /></form>);
}export default App;

例子:在组件树中使用
useId 在组件树中使用时,每个组件实例都会生成不同的 ID。这意味着即使在嵌套组件中多次使用 useId,也不会产生冲突

import React, { useId } from 'react';function InputWithLabel({ labelText }) {const id = useId();return (<div><label htmlFor={id}>{labelText}</label><input type="text" id={id} /></div>);
}function App() {return (<div><InputWithLabel labelText="用户名" /><InputWithLabel labelText="密码" /></div>);
}export default App;

hook 初始化入口

hook是函数组件中的钩子函数。在函数组件渲染的过程中会调用renderWithHooks函数。

renderWithHooks

函数参数含义:

  • current:旧的 Fiber 节点,如果是首次渲染则为 null。
  • workInProgress:当前正在处理的新 Fiber 节点。
  • Component:要渲染的函数式组件,它接收 props 和 secondArg 作为参数,并返回 JSX 元素。
  • props:传递给组件的属性。
  • secondArg:额外的参数。
  • nextRenderLanes:下一次渲染的优先级车道。
function renderWithHooks<Props, SecondArg>(current: Fiber | null,workInProgress: Fiber,Component: (p: Props, arg: SecondArg) => any,props: Props,secondArg: SecondArg,nextRenderLanes: Lanes,
): any {// 确定当前渲染的优先级。renderLanes = nextRenderLanes;// 将 currentlyRenderingFiber 指向 workInProgress,表示当前正在渲染这个 Fiber 节点。currentlyRenderingFiber = workInProgress;// 重置信息workInProgress.memoizedState = null;workInProgress.updateQueue = null;workInProgress.lanes = NoLanes;//钩子调度器,区分是初始化还是更新ReactSharedInternals.H =current === null || current.memoizedState === null? HooksDispatcherOnMount: HooksDispatcherOnUpdate;//调用函数组件let children = Component(props, secondArg);// 调用 finishRenderingHooks 函数,进行一些渲染完成后的清理和处理工作,例如处理副作用钩子的执行等。finishRenderingHooks(current, workInProgress, Component);return children;
}
// renderLanes:表示当前渲染的优先级车道,初始值为 NoLanes(通常为 0),用于标识渲染任务的优先级。
let renderLanes: Lanes = NoLanes;//默认0// 指向当前正在渲染的 Fiber 节点,初始为 null。Fiber 是 React 中的一种数据结构,用于表示组件树中的每个节点。
let currentlyRenderingFiber: Fiber = (null: any);// 当前的钩子
let currentHook: Hook | null = null;//正在处理的钩子
let workInProgressHook: Hook | null = null;

所以初始化用HooksDispatcherOnMount,更新使用HooksDispatcherOnUpdate

HooksDispatcherOnMount

const HooksDispatcherOnMount: Dispatcher = {readContext,use,useCallback: mountCallback,useContext: readContext,useEffect: mountEffect,useImperativeHandle: mountImperativeHandle,useLayoutEffect: mountLayoutEffect,useInsertionEffect: mountInsertionEffect,useMemo: mountMemo,useReducer: mountReducer,useRef: mountRef,useState: mountState,useDebugValue: mountDebugValue,useDeferredValue: mountDeferredValue,useTransition: mountTransition,useSyncExternalStore: mountSyncExternalStore,useId: mountId,
};

HooksDispatcherOnUpdate

const HooksDispatcherOnUpdate: Dispatcher = {readContext,use,useCallback: updateCallback,useContext: readContext,useEffect: updateEffect,useImperativeHandle: updateImperativeHandle,useInsertionEffect: updateInsertionEffect,useLayoutEffect: updateLayoutEffect,useMemo: updateMemo,useReducer: updateReducer,useRef: updateRef,useState: updateState,useDebugValue: updateDebugValue,useDeferredValue: updateDeferredValue,useTransition: updateTransition,useSyncExternalStore: updateSyncExternalStore,useId: updateId,
};

useId初始化

function useId(): string {
//resolveDispatcher 是 React 内部的一个函数,它的作用是获取当前的调度器(dispatcher)const dispatcher = resolveDispatcher();// dispatcher.useId() 调用了调度器对象的 useId 方法。这个方法会生成一个全局唯一的 ID 字符串,并将其返回。return dispatcher.useId();
}

resolveDispatcher

function resolveDispatcher() {// 从 ReactSharedInternals 对象中获取名为 H 的属性,并将其赋值给变量 dispatcher。ReactSharedInternals 是 React 内部使用的一个共享对象,它包含了一些 React 运行时的关键信息和工具。H 属性在这里代表着当前 React 环境下的调度器实例。const dispatcher = ReactSharedInternals.H;// 将获取到的调度器实例 dispatcher 返回给调用者。这样,调用 resolveDispatcher 函数的代码就可以使用这个调度器来执行各种调度相关的操作,比如调用调度器的 useState 方法来处理状态管理。return dispatcher;
}

mountId

mountId 函数是 React 中 useId Hook 在挂载阶段(组件首次渲染)用于生成全局唯一 ID 的核心实现。该函数会根据当前是服务端渲染(SSR)还是客户端渲染的不同情况,生成不同格式的唯一 ID,并将其存储在 Fiber 节点对应的 hook 对象的 memoizedState 属性上,最后返回这个唯一 ID。

function mountId(): string {//创建 hook 对象,将 hook 对象添加到 workInProgressHook 单向链表中,返回最新的 hook 链表const hook = mountWorkInProgressHook();
//getWorkInProgressRoot() 方法获取当前的 FiberRoot 对象const root = ((getWorkInProgressRoot(): any): FiberRoot);//从 FiberRoot 对象 上获取id前缀const identifierPrefix = root.identifierPrefix;let id;// 调用 getIsHydrating() 方法判断是服务端渲染还是客户端渲染if (getIsHydrating()) {//服务端渲染注水(hydrate)阶段生成的唯一 id,以冒号开头,并以冒号结尾,使用大写字母 R 标识该id是服务端渲染生成的id//获取组件树的idconst treeId = getTreeId();// Use a captial R prefix for server-generated ids.id = ':' + identifierPrefix + 'R' + treeId;// localIdCounter 变量记录组件中 useId 的执行次数const localId = localIdCounter++;if (localId > 0) {id += 'H' + localId.toString(32);}id += ':';} else {//客户端渲染生成的唯一 id,以冒号开头,并以冒号结尾,使用小写字母 r 标识该id 是客户端渲染生成的id//全局变量 globalClientIdCounter 记录 useId hook 在组件中的调用次数const globalClientId = globalClientIdCounter++;// globalClientIdCounter初始值为0id = ':' + identifierPrefix + 'r' + globalClientId.toString(32) + ':';}// 将生成的唯一 id 存储到 hook 对象的 memoizedState 属性上hook.memoizedState = id;return id;
}

以下代码可以看到useId的返回值的格式

id = ':' + identifierPrefix + 'r' + globalClientId.toString(32) + ':';
// ':r0:'

如何在挂载的时候加入配置项identifierPrefix

ReactDOM.createRoot(document.getElementById('box'),{identifierPrefix: 'testyoyo'
});
id = ':' + identifierPrefix + 'r' + globalClientId.toString(32) + ':';
//:testyoyor0:

updateId

当函数组件刷新时,重新构建hook链表时,遇到useId会执行以下代码

function updateId(): string {//  获取当前的 workInProgressHookconst hook = updateWorkInProgressHook();// 从当前的 workInProgressHook 上获取 useId 生成的 id,因此即使组件重新渲染,id 也不会变化const id: string = hook.memoizedState;return id;
}

工具函数 mountWorkInProgressHook

mountWorkInProgressHook 函数主要用于在 React 的渲染过程中,为当前正在处理的 Fiber 节点(currentlyRenderingFiber)挂载一个新的 Hook。
Hook 是 React 中用于在函数组件中使用状态和副作用的机制,这个函数负责初始化 Hook 对象,并将其添加到当前 Fiber 节点的 Hook 链表中。

function mountWorkInProgressHook(): Hook {// 初始化hook对象const hook: Hook = {memoizedState: null,//用于存储当前 Hook 的状态值,在使用 useState 或 useReducer 等钩子时会更新这个值。baseState: null,// 表示状态的基础值,在处理更新队列时会用到。baseQueue: null,// 存储尚未处理的更新队列,通常与 baseState 配合使用。queue: null,// 存储当前 Hook 的更新队列,用于存储状态更新的操作。next: null,// 用于将多个 Hook 对象连接成一个链表,指向下一个 Hook 对象。};// 如果 workInProgressHook 为 null,说明这是当前 Fiber 节点的第一个 Hook。if (workInProgressHook === null) {// 将 currentlyRenderingFiber 的 memoizedState 属性设置为新创建的 Hook 对象,并将 workInProgressHook 也指向这个 Hook 对象。这样,currentlyRenderingFiber 的 memoizedState 就成为了 Hook 链表的头节点。currentlyRenderingFiber.memoizedState = workInProgressHook = hook;} else {// Append to the end of the list// 如果 workInProgressHook 不为 null,说明当前 Fiber 节点已经有其他 Hook 存在。此时,将新创建的 Hook 对象添加到 Hook 链表的末尾。workInProgressHook = workInProgressHook.next = hook;}// 返回当前正在处理的 Hook 对象return workInProgressHook;
}

在这里插入图片描述

export type Hook = {memoizedState: any,baseState: any,baseQueue: Update<any, any> | null,queue: any,next: Hook | null,
};

当前Fiber 节点与 hook 链表的关联关系图

在这里插入图片描述

工具函数 updateWorkInProgressHook

updateWorkInProgressHook 函数是 React 内部用于更新和管理 Hook 的核心函数之一。在 React 的更新过程中,组件可能会重新渲染,而 Hook 也需要相应地更新。这个函数的主要目的是在新旧 Fiber 节点的 Hook 链表之间进行同步和复用,确保 Hook 的状态能够正确地传递和更新。

function updateWorkInProgressHook(): Hook {// 确定下一个当前 Hook(nextCurrentHook)let nextCurrentHook: null | Hook;// currentHook表示当前正在处理的旧 Hook// 当 currentHook 为 null 时,说明是处理第一个 Hook。if (currentHook === null) {// currentlyRenderingFiber.alternate 指向的是上一次渲染的 Fiber 节点(双缓冲机制中的旧 Fiber)const current = currentlyRenderingFiber.alternate;// 如果该旧 Fiber 存在,就从其 memoizedState 中获取第一个旧 Hook;if (current !== null) {nextCurrentHook = current.memoizedState;// fiber存在的hookl链表} else {// 若不存在,则 nextCurrentHook 为 null。nextCurrentHook = null;}} else {// 当 currentHook 不为 null 时,nextCurrentHook 就是当前旧 Hook 的下一个 Hook。nextCurrentHook = currentHook.next;}// 确定下一个工作中的 Hook(nextWorkInProgressHook)let nextWorkInProgressHook: null | Hook;// workInProgressHook 表示当前正在构建的新 Fiber 节点中的 Hook。if (workInProgressHook === null) {// 若 workInProgressHook 为 null,说明是处理第一个 Hook,则从当前正在渲染的 Fiber 节点的 memoizedState 中获取第一个 Hook 作为 nextWorkInProgressHooknextWorkInProgressHook = currentlyRenderingFiber.memoizedState;} else {// 若不为 null,则 nextWorkInProgressHook 就是当前 workInProgressHook 的下一个 Hook。nextWorkInProgressHook = workInProgressHook.next;}// 若 nextWorkInProgressHook 不为 null,说明已经有正在构建的 Hook 可以复用。if (nextWorkInProgressHook !== null) {// 将 workInProgressHook 更新为 nextWorkInProgressHook,并更新 nextWorkInProgressHook 为其下一个 Hook。workInProgressHook = nextWorkInProgressHook;nextWorkInProgressHook = workInProgressHook.next;// 同时,将 currentHook 更新为 nextCurrentHook。currentHook = nextCurrentHook;} else {// 若 nextWorkInProgressHook 为 null,说明没有现成的工作中的 Hook 可以复用,需要克隆旧 Hook 到新 Hook。if (nextCurrentHook === null) {const currentFiber = currentlyRenderingFiber.alternate;}
// 先将 currentHook 更新为 nextCurrentHook。currentHook = nextCurrentHook;// 创建一个新的 Hook 对象 newHook,将旧 Hook 的 memoizedState、baseState、baseQueue 和 queue 复制到新 Hook 中。const newHook: Hook = {memoizedState: currentHook.memoizedState,baseState: currentHook.baseState,baseQueue: currentHook.baseQueue,queue: currentHook.queue,next: null,};// 如果 workInProgressHook 为 null,说明这是 Hook 链表的第一个 Hookif (workInProgressHook === null) {// This is the first hook in the list.// 将 currentlyRenderingFiber.memoizedState 和 workInProgressHook 都指向新 Hook;currentlyRenderingFiber.memoizedState = workInProgressHook = newHook;} else {// Append to the end of the list.// 若不为 null,则将新 Hook 添加到 Hook 链表的末尾。workInProgressHook = workInProgressHook.next = newHook;}}// 返回当前工作中的 Hookreturn workInProgressHook;
}

在这里插入图片描述

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

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

相关文章

Redisson 分布式锁原理

加锁原理 # 如果锁不存在 if (redis.call(exists, KEYS[1]) 0) then# hash结构,锁名称为key,线程唯一标识为itemKey&#xff0c;itemValue为一个计数器。支持相同客户端线程可重入,每次加锁计数器1.redis.call(hincrby, KEYS[1], ARGV[2], 1);# 设置过期时间redis.call(pexpi…

单元化架构在字节跳动的落地实践

资料来源&#xff1a;火山引擎-开发者社区 什么是单元化 单元化的核心理念是将业务按照某种维度划分成一个个单元&#xff0c; 理想情况下每个单元内部都是完成所有业务操作的自包含集合&#xff0c;能独立处理业务流程&#xff0c;各个单元均有其中一部分数据&#xff0c;所有…

基于Python的垃圾短信分类

垃圾短信分类 1 垃圾短信分类问题介绍 1.1 垃圾短信 随着移动互联科技的高速发展&#xff0c;信息技术在不断改变着我们的生活&#xff0c;让我们的生活更方便&#xff0c;其中移动通信技术己经在我们生活起到至关重要的作用&#xff0c;与我们每个人人息息相关。短信作为移…

leetcode1971.寻找图中是否存在路径

初尝并查集&#xff0c;直接套用模板 class Solution { private:vector<int> father;void init() {for(int i0;i<father.size();i)father[i]i;}int find(int v) {return vfather[v]?v:father[v]find(father[v]);//路径压缩}bool isSame(int u,int v){ufind(u);vfind…

QAI AppBuilder 快速上手(7):目标检测应用实例

YOLOv8_det是YOLO 系列目标检测模型&#xff0c;专为高效、准确地检测图像中的物体而设计。该模型通过引入新的功能和改进点&#xff0c;如因式分解卷积&#xff08;factorized convolutions&#xff09;和批量归一化&#xff08;batch normalization&#xff09;&#xff0c;在…

景联文科技:以高质量数据标注推动人工智能领域创新与发展

在当今这个由数据驱动的时代&#xff0c;高质量的数据标注对于推动机器学习、自然语言处理&#xff08;NLP&#xff09;、计算机视觉等领域的发展具有不可替代的重要性。数据标注过程涉及对原始数据进行加工&#xff0c;通过标注特定对象的特征来生成能够被机器学习模型识别和使…

MySQL 索引下推

概念 索引下推&#xff08;Index Condition Pushdown&#xff0c;简称 ICP&#xff09; 是 MySQL 5.6 版本中提供的一项索引优化功能&#xff0c;它允许存储引擎在索引遍历过程中&#xff0c;执行部分 WHERE字句的判断条件&#xff0c;直接过滤掉不满足条件的记录&#xff0c;…

Unity | 游戏数据配置

目录 一、ScriptableObject 1.创建ScriptableObject 2.创建asset资源 3.asset资源的读取与保存 二、Excel转JSON 1.Excel格式 2.导表工具 (1)处理A格式Excel (2)处理B格式Excel 三、解析Json文件 1.读取test.json文件 四、相关插件 在游戏开发中,策划…

2025信创即时通讯排行:安全合规与生态适配双轮驱动

随着信息技术应用创新&#xff08;信创&#xff09;战略的深化&#xff0c;国产即时通讯工具在政企市场的渗透率显著提升。2025年作为“十四五”规划收官之年&#xff0c;信创产业迎来规模化应用关键节点。本文将从认证标准、市场表现、技术架构、行业适配四大维度&#xff0c;…

关于TVS管漏电流的问题?

问题描述&#xff1a; 在量产的带电池故事机生产中&#xff0c;工厂产线测试电流时&#xff0c;有1台机器电流比正常机器大10mA左右。 原因分析&#xff1a; 1、分析电路原理图&#xff0c;去除可能出现问题的电压或器件&#xff08;不影响系统&#xff09;&#xff0c;发现…

RAG 架构地基工程-Retrieval 模块的系统设计分享

目录 一、知识注入的关键前奏——RAG 系统中的检索综述 &#xff08;一&#xff09;模块定位&#xff1a;连接语言模型与知识世界的桥梁 &#xff08;二&#xff09;核心任务&#xff1a;四大关键问题的协调解法 &#xff08;三&#xff09;系统特征&#xff1a;性能、精度…

Java-servlet(七)详细讲解Servlet注解

Java-servlet&#xff08;七&#xff09;详细讲解Servlet注解 前言一、注解的基本概念二、Override 注解2.1 作用与优势2.2 示例代码 三、Target 注解3.1 定义与用途3.2 示例代码 四、WebServlet 注解4.1 作用4.2 示例代码 五、反射与注解5.1 反射的概念5.2 注解与反射的结合使…

机器学习——分类、回归、聚类、LASSO回归、Ridge回归(自用)

纠正自己的误区&#xff1a;机器学习是一个大范围&#xff0c;并不是一个小的方向&#xff0c;比如&#xff1a;线性回归预测、卷积神经网络和强化学都是机器学习算法在不同场景的应用。 机器学习最为关键的是要有数据&#xff0c;也就是数据集 名词解释&#xff1a;数据集中的…

本地AI大模型工具箱 Your local AI toolkit:LMStudio

LMStudio介绍 官网&#xff1a;LM Studio - Discover, download, and run local LLMs LMStudio 是一个面向机器学习和自然语言处理的&#xff0c;旨在使开发者更容易构建和部署AI语言模型的应用软件。 LMStudio的特点是&#xff1a; 完全本地离线运行AI大模型 可以从Huggi…

[OpenCV】相机标定之棋盘格角点检测与绘制

在OpenCV中&#xff0c;棋盘格角点检测与绘制是一个常见的任务&#xff0c;通常用于相机标定。 棋盘格自定义可参考: OpenCV: Create calibration pattern 目录 1. 棋盘格角点检测 findChessboardCorners()2. 棋盘格角点绘制 drawChessboardCorners()3. 代码示例C版本python版本…

redis的典型应用 --缓存

Redis最主要的用途&#xff0c;分为三个方面&#xff1a; 1.存储数据&#xff08;内存数据库&#xff09; 2.缓存&#xff08;最常用&#xff09; 3.消息队列 缓存 (cache) 是计算机中的⼀个经典的概念。核⼼思路就是把⼀些常⽤的数据放到触⼿可及(访问速度更快)的地⽅&…

本地基于Ollama部署的DeepSeek详细接口文档说明

前文&#xff0c;我们已经在本地基于Ollama部署好了DeepSeek大模型&#xff0c;并且已经告知过如何查看本地的API。为了避免网络安全问题&#xff0c;我们希望已经在本地调优的模型&#xff0c;能够嵌入到在本地的其他应用程序中&#xff0c;发挥本地DeepSeek的作用。因此需要知…

基于ArcGIS和ETOPO-2022 DEM数据分层绘制全球海陆分布

第〇部分 前言 一幅带有地理空间参考、且包含海陆分布的DEM图像在研究区的绘制中非常常见&#xff0c;本文将实现以下图像的绘制 关键步骤&#xff1a; &#xff08;1&#xff09;NOAA-NCEI官方下载最新的ETOPO-2022 DEM数据 &#xff08;2&#xff09;在ArcGIS&#xff08;…

Retrofit中scalars转换html为字符串

简介 在Retrofit中&#xff0c;如果你想直接获取HTML或其他文本格式的响应内容而不是将其映射到一个模型类&#xff0c;ScalarsConverterFactory 就派上用场了。ScalarsConverterFactory 是一个转换器工厂&#xff0c;它能够将响应体转换为Java基本类型如String、Integer或Byte…

Powershell WSL Windows系统复制数据到ubuntu子系统系统

从本地D盘下拷贝数据到ubuntu子系统下 Powershell 管理员打开执行 /mnt/d 此处是本地Windows系统的路径表示/opt ubutu 子系统目录 wsl -d Ubuntu-22.04 -u root -- bash -c cp -rf /mnt/d/nginx.conf /opt/从ubuntu子系统中拷贝数据到本地D盘下 Powershell 管理员打开执行…