React19源码系列之 API(react-dom)
API之 preconnect
preconnect – React 中文文档
preconnect
函数向浏览器提供一个提示,告诉它应该打开到给定服务器的连接。如果浏览器选择这样做,则可以加快从该服务器加载资源的速度。
preconnect(href)
一、使用例子
import { preconnect } from 'react-dom';function AppRoot() {preconnect("https://example.com");return ...;
}
import { preconnect } from 'react-dom';function CallToAction() {const onClick = () => {preconnect('http://example.com');startWizard();}return (<button onClick={onClick}>Start Wizard</button>);
}
二、源码
function preconnect(href: string, options?: ?PreconnectOptions) {if (typeof href === 'string') {const crossOrigin = options? getCrossOriginString(options.crossOrigin): null;ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */.C(/* preconnect */ href, crossOrigin);}
}
ReactDOMSharedInternals.d.C
preconnect
函数的主要功能是发起一个 preconnect
操作,用于提前建立与指定 href
对应的服务器连接。
function preconnect(href: string, crossOrigin?: ?CrossOriginEnum) {previousDispatcher.C(/* preconnect */ href, crossOrigin);preconnectAs('preconnect', href, crossOrigin);
}
API之 prefetchDNS
prefetchDNS – React 中文文档
prefetchDNS
函数向浏览器提供一个提示,告诉它应该查找给定服务器的 IP 地址。如果浏览器选择这样做,则可以加快从该服务器加载资源的速度。
一、使用示范
prefetchDNS
允许提前查找期望从中加载资源的服务器的 IP。
prefetchDNS("https://example.com");
二、源码分析
function prefetchDNS(href: string) {if (typeof href === 'string') {ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */.D(/* prefetchDNS */ href);}
}
ReactDOMSharedInternals.d.D
prefetchDNS
函数的主要作用是预获取指定 href
对应的 DNS 信息。
function prefetchDNS(href: string) {previousDispatcher.D(/* prefetchDNS */ href);preconnectAs('dns-prefetch', href, null);
}
preconnectAs
preconnectAs
函数用于创建 rel="preconnect"
或 rel="dns-prefetch"
的 link
元素,以提前建立与目标服务器的连接或解析 DNS,从而优化后续资源加载的性能。它会检查是否已存在相同配置的预连接标签,避免重复创建。
function preconnectAs(rel: 'preconnect' | 'dns-prefetch',href: string,crossOrigin: ?CrossOriginEnum,
) {// 获取documentconst ownerDocument = getGlobalDocument();if (ownerDocument && typeof href === 'string' && href) {const limitedEscapedHref =escapeSelectorAttributeValueInsideDoubleQuotes(href);// let key = `link[rel="${rel}"][href="${limitedEscapedHref}"]`;if (typeof crossOrigin === 'string') {key += `[crossorigin="${crossOrigin}"]`;}if (!preconnectsSet.has(key)) {preconnectsSet.add(key);const preconnectProps = {rel, crossOrigin, href};if (null === ownerDocument.querySelector(key)) {const instance = ownerDocument.createElement('link');// 设置link元素的属性setInitialProperties(instance, 'link', preconnectProps);// 标记可提升markNodeAsHoistable(instance);// 往head元素中添加子元素link标签(ownerDocument.head: any).appendChild(instance);}}}
}
类型 | 作用 | 使用场景 |
preconnect | 提前建立完成连接。(包括dns解析、tcp握手和 TLS协商) | 确定会理解加载跨域资源(如字体、API) |
dns-prefetch | 仅提前解析dns,不建立TCP、TLS连接。 | 可能会在未来加载的资源(如广告、第三方内容),减少dns解析延迟。 |
API之 preinit
preinit – React 中文文档
preinit
函数向浏览器提供一个提示,告诉它应该开始下载并执行给定的资源,这可以节省时间。preinit
的脚本在下载完成后执行。预初始化的样式表被插入到文档中,这会使它们立即生效。
preinit(href, options)
参数
href
:字符串,要下载并执行的资源的 URL。options
:对象,可以包含以下属性:as
:必需的字符串,表示资源的类型,可能的值包括script
与style
。precedence
:字符串,与样式表一起使用时必需。指定样式表相对于其他样式表的插入位置。具有较高优先级的样式表可以覆盖具有较低优先级的样式表,可能的值包括reset
、low
、medium
与high
。crossOrigin
:字符串,表示要使用的 CORS 策略,可能的值为anonymous
与use-credentials
。integrity
:字符串,为资源的加密哈希,用于 验证其真实性。nonce
:字符串,表示使用严格内容安全策略时允许资源的 加密随机数。fetchPriority
:字符串,表示建议获取资源的相对优先级,可能的值为auto
(默认值)、high
与low
。
一、使用例子
1、加载script资源
import { preinit } from 'react-dom';function AppRoot() {preinit("https://example.com/script.js", {as: "script"});return ...;
}
2、加载style样式资源
import { preinit } from 'react-dom';function AppRoot() {preinit("https://example.com/style.css", {as: "style", precedence: "medium"});return ...;
}
3、在事件程序中使用加载资源
import { preinit } from 'react-dom';function CallToAction() {const onClick = () => {preinit("https://example.com/wizardStyles.css", {as: "style"});startWizard();}return (<button onClick={onClick}>Start Wizard</button>);
}
二、源码
function preinit(href: string, options: PreinitOptions) {if (typeof href === 'string' && options && typeof options.as === 'string') {// 获取要下载的资源类型const as = options.as;// 获取crossorigin属性的值,可能为use-credentials、空字符串或undefinedconst crossOrigin = getCrossOriginStringAs(as, options.crossOrigin);// 资源加密哈希const integrity =typeof options.integrity === 'string' ? options.integrity : undefined;// 资源优先级const fetchPriority =typeof options.fetchPriority === 'string'? options.fetchPriority: undefined;// 资源为样式表if (as === 'style') {ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */.S(/* preinitStyle */href,// 资源链接typeof options.precedence === 'string'? options.precedence: undefined,// 资源优先级{crossOrigin,//integrity,//fetchPriority,//},);// 资源为script脚本} else if (as === 'script') {ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */.X(/* preinitScript */ href, {crossOrigin,integrity,fetchPriority,nonce: typeof options.nonce === 'string' ? options.nonce : undefined,//安全策略随机数});}}
}
ReactDOMSharedInternals.d.S(preinitStyle)
preinitStyle
函数的主要功能是预处理样式资源。它会检查指定的样式资源(通过 href
标识)是否已存在于全局文档的样式资源中。如果不存在,会创建一个新的样式资源实例(link
元素),设置其属性,并插入到文档中,同时缓存该资源的相关信息。
function preinitStyle(href: string,precedence: ?string,options?: ?PreinitStyleOptions,
) {previousDispatcher.S(/* preinitStyle */ href, precedence, options);// 获取document对象const ownerDocument = getGlobalDocument();if (ownerDocument && href) {// 获取样式表信息,map类型const styles = getResourcesFromRoot(ownerDocument).hoistableStyles;// 将href解析返回 格式为‘href=xxxxx’const key = getStyleKey(href);precedence = precedence || 'default';// Check if this resource already existslet resource = styles.get(key);if (resource) {// We can early return. The resource exists and there is nothing// more to doreturn;}// 初始化资源const state = {loading: NotLoaded,preload: null,};// Attempt to hydrate instance from DOM// 查询选取器let instance: null | Instance = ownerDocument.querySelector(// `link[rel="stylesheet"][${key}]`getStylesheetSelectorFromKey(key),);if (instance) {// 资源已加载并插入state.loading = Loaded | Inserted;} else {// Construct a new instance and insert it// 处理link相关属性const stylesheetProps = Object.assign(({rel: 'stylesheet',href,'data-precedence': precedence,}: StylesheetProps),options,);const preloadProps = preloadPropsMap.get(key);if (preloadProps) {// 设置stylesheetProps对象中的属性,如title,crossOrigin,refferPolicyadoptPreloadPropsForStylesheet(stylesheetProps, preloadProps);}// 创建link标签const link = (instance = ownerDocument.createElement('link'));//标记markNodeAsHoistable(link);// 设置属性setInitialProperties(link, 'link', stylesheetProps);// 为link设置promise(link: any)._p = new Promise((resolve, reject) => {link.onload = resolve;link.onerror = reject;});// 处理 load 和 error 事件link.addEventListener('load', () => {state.loading |= Loaded;});link.addEventListener('error', () => {state.loading |= Errored;});state.loading |= Inserted;// 插入文档insertStylesheet(instance, precedence, ownerDocument);}// Construct a Resource and cache itresource = {type: 'stylesheet',instance,count: 1,state,};// 缓存资源styles.set(key, resource);return;}
}const preloadPropsMap: Map<string, PreloadProps | PreloadModuleProps> =new Map();
type LoadingState = number;
const NotLoaded = /* */ 0b000;//0 未加载
const Loaded = /* */ 0b001;//1 加载
const Errored = /* */ 0b010;//2 出错
const Settled = /* */ 0b011;//3
const Inserted = /* */ 0b100;//4 插入
type StylesheetProps = {rel: 'stylesheet',href: string,'data-precedence': string,[string]: mixed,
};
function adoptPreloadPropsForStylesheet(stylesheetProps: StylesheetProps,preloadProps: PreloadProps | PreloadModuleProps,
): void {if (stylesheetProps.crossOrigin == null)stylesheetProps.crossOrigin = preloadProps.crossOrigin;if (stylesheetProps.referrerPolicy == null)stylesheetProps.referrerPolicy = preloadProps.referrerPolicy;if (stylesheetProps.title == null) stylesheetProps.title = preloadProps.title;
}
ReactDOMSharedInternals.d.X(preinitScript)
preinitScript
函数的主要功能是预初始化 JavaScript 脚本资源。它会检查指定 src
的脚本是否已存在于文档中,如果不存在则创建并插入一个新的 script
标签,同时缓存该资源的相关信息。该函数支持从现有 DOM 中复用脚本实例,也能处理预加载属性,并确保脚本以异步方式加载。
function preinitScript(src: string, options?: ?PreinitScriptOptions) {previousDispatcher.X(/* preinitScript */ src, options);// 获取document对象const ownerDocument = getGlobalDocument();if (ownerDocument && src) {// 获取资源const scripts = getResourcesFromRoot(ownerDocument).hoistableScripts;// src=xxxxconst key = getScriptKey(src);// Check if this resource already existslet resource = scripts.get(key);if (resource) {// We can early return. The resource exists and there is nothing// more to doreturn;}// Attempt to hydrate instance from DOMlet instance: null | Instance = ownerDocument.querySelector(getScriptSelectorFromKey(key),);if (!instance) {// Construct a new instance and insert itconst scriptProps = Object.assign(({src,async: true,// 异步加载}: ScriptProps),options,);// Adopt certain preload propsconst preloadProps = preloadPropsMap.get(key);if (preloadProps) {// 设置属性integrity、referrerPolicy、crossOriginadoptPreloadPropsForScript(scriptProps, preloadProps);}// 创建script标签instance = ownerDocument.createElement('script');// 打标记markNodeAsHoistable(instance);// 设置属性setInitialProperties(instance, 'link', scriptProps);// 添加(ownerDocument.head: any).appendChild(instance);}// Construct a Resource and cache itresource = {type: 'script',instance,count: 1,state: null,};scripts.set(key, resource);return;}
}
function getScriptSelectorFromKey(key: string): string {return 'script[async]' + key;
}
function adoptPreloadPropsForScript(scriptProps: ScriptProps,preloadProps: PreloadProps | PreloadModuleProps,
): void {if (scriptProps.crossOrigin == null)scriptProps.crossOrigin = preloadProps.crossOrigin;if (scriptProps.referrerPolicy == null)scriptProps.referrerPolicy = preloadProps.referrerPolicy;if (scriptProps.integrity == null)scriptProps.integrity = preloadProps.integrity;
}
API之 preinitModule
preinitModule – React 中文文档
preinitModule
函数向浏览器提供一个提示,告诉它应该开始下载并执行给定的模块,这可以节省时间。预初始化的模块在下载完成后执行。
preinitModule(href, options)
参数
href
:字符串,要下载并执行的模块的 URL。options
:对象,可以包含以下属性:as
:必需的字符串,只能是script
。crossOrigin
:字符串,表示要使用的 CORS 策略,可能的值为anonymous
与use-credentials
。integrity
:字符串,为资源的加密哈希,用于 验证其真实性。nonce
:字符串,表示使用严格内容安全策略时允许资源的 加密随机数。
一、使用示范
import { preinitModule } from 'react-dom';function AppRoot() {preinitModule("https://example.com/module.js", {as: "script"});return ...;
}
import { preinitModule } from 'react-dom';function CallToAction() {const onClick = () => {preinitModule("https://example.com/module.js", {as: "script"});startWizard();}return (<button onClick={onClick}>Start Wizard</button>);
}
二、源码分析
function preinitModule(href: string, options?: ?PreinitModuleOptions) {if (typeof href === 'string') {if (typeof options === 'object' && options !== null) {if (options.as == null || options.as === 'script') {const crossOrigin = getCrossOriginStringAs(options.as,options.crossOrigin,);ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */.M(/* preinitModuleScript */ href, {crossOrigin,integrity:typeof options.integrity === 'string'? options.integrity: undefined,nonce:typeof options.nonce === 'string' ? options.nonce : undefined,});}} else if (options == null) {ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */.M(/* preinitModuleScript */ href);}}
}
ReactDOMSharedInternals.d.M
preinitModuleScript
函数的核心功能是预初始化 ES6 模块脚本资源。它会检查指定 src
的模块脚本是否已存在于文档中,如果不存在则创建并插入一个新的 script
标签(设置为 type="module"
),同时缓存该资源的相关信息。
function preinitModuleScript(src: string,options?: ?PreinitModuleScriptOptions,
) {previousDispatcher.M(/* preinitModuleScript */ src, options);// 获取document对象const ownerDocument = getGlobalDocument();if (ownerDocument && src) {// 获取资源const scripts = getResourcesFromRoot(ownerDocument).hoistableScripts;const key = getScriptKey(src);// Check if this resource already existslet resource = scripts.get(key);if (resource) {// We can early return. The resource exists and there is nothing// more to doreturn;}// Attempt to hydrate instance from DOMlet instance: null | Instance = ownerDocument.querySelector(getScriptSelectorFromKey(key),);if (!instance) {// Construct a new instance and insert itconst scriptProps = Object.assign(({src,async: true,//异步加载type: 'module',// 模块}: ScriptProps),options,);// Adopt certain preload propsconst preloadProps = preloadPropsMap.get(key);if (preloadProps) {// 如果存在预加载属性 preloadProps,则将其应用到脚本属性中(如 integrity、referrerPolicy、crossOrigin 等)。adoptPreloadPropsForScript(scriptProps, preloadProps);}instance = ownerDocument.createElement('script');// 标记可提升markNodeAsHoistable(instance);setInitialProperties(instance, 'link', scriptProps);(ownerDocument.head: any).appendChild(instance);}// Construct a Resource and cache itresource = {type: 'script',instance,count: 1,state: null,};scripts.set(key, resource);return;}
}
API之 preload
preload – React 中文文档
preload
函数的主要作用是对资源进行预加载操作。它会先对传入的参数进行有效性检查,确保参数类型符合要求,然后触发资源的预加载。
preload(href, options)
参数
- href:字符串,要下载的资源的 URL。
- options:对象,可以包含以下属性:
as
:必需的字符串,表示资源的类型,可能的值 包括 audio、document、embed、fetch、font、image、object、script、style、track、video 与 worker。crossOrigin
:字符串,表示要使用的 CORS 策略,可能的值为 anonymous 与 use-credentials。当 as 设置为 "fetch" 时是必需的。referrerPolicy
:字符串,表示在获取时发送的 referer 请求头,可能的值为 no-referrer-when-downgrade(默认值)、no-referrer、origin、origin-when-cross-origin 与 unsafe-url。integrity
:字符串,为资源的加密哈希,用于 验证其真实性。type
:字符串,表示资源的 MIME 类型。nonce
:字符串,表示使用严格内容安全策略时允许资源的 加密随机数。fetchPriority
:字符串,为获取资源建议的相对优先级,可能的值为 auto(默认值)、high 与 low。imageSrcSet
:字符串,仅与 as: "image" 一起使用,用于指定 图像的源集。imageSizes
:字符串,仅与 as: "image" 一起使用,用于指定 图像的尺寸。
一、使用示范
- 渲染时进行预加载
- 在事件处理程序中预加载
preload 可以预获取期望使用的资源,比如样式表、字体或外部脚本。
preload("https://example.com/font.woff2", {as: "font"});
import { preload } from 'react-dom';function AppRoot() {preload("https://example.com/style.css", {as: "style"});preload("https://example.com/font.woff2", {as: "font"});return ...;
}
二、源码
function preload(href: string, options: PreloadOptions) {if (typeof href === 'string' &&typeof options === 'object' &&options !== null &&typeof options.as === 'string') {// as:从 options 对象中提取 as 属性的值,该属性通常用于指定预加载资源的类型,如 'script'、'style' 等。const as = options.as;// 调用 getCrossOriginStringAs 函数,根据 as 和 options.crossOrigin 生成跨域相关的字符串。const crossOrigin = getCrossOriginStringAs(as, options.crossOrigin);ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */.L(/* preload */ href, as, {crossOrigin,integrity:typeof options.integrity === 'string' ? options.integrity : undefined,nonce: typeof options.nonce === 'string' ? options.nonce : undefined,type: typeof options.type === 'string' ? options.type : undefined,fetchPriority:typeof options.fetchPriority === 'string'? options.fetchPriority: undefined,referrerPolicy:typeof options.referrerPolicy === 'string'? options.referrerPolicy: undefined,imageSrcSet:typeof options.imageSrcSet === 'string'? options.imageSrcSet: undefined,imageSizes:typeof options.imageSizes === 'string'? options.imageSizes: undefined,media: typeof options.media === 'string' ? options.media : undefined,});}
}
ReactDOMSharedInternals.d.L
preload
函数主要用于预加载资源,通过创建 rel="preload"
的 link
元素来实现。它会根据资源的类型(as
)和相关选项(options
)生成合适的选择器和属性,检查资源是否已存在于文档中,若不存在则插入新的 link
元素进行预加载,同时处理 Safari 中关于图片 imageSrcSet
的特殊情况。
function preload(href: string, as: string, options?: ?PreloadImplOptions) {previousDispatcher.L(/* preload */ href, as, options);// 获取document对象const ownerDocument = getGlobalDocument();if (ownerDocument && href && as) {// 预加载选择器let preloadSelector = `link[rel="preload"][as="${escapeSelectorAttributeValueInsideDoubleQuotes(as,)}"]`;// 当资源类型为image时,处理if (as === 'image') {if (options && options.imageSrcSet) {preloadSelector += `[imagesrcset="${escapeSelectorAttributeValueInsideDoubleQuotes(options.imageSrcSet,)}"]`;if (typeof options.imageSizes === 'string') {preloadSelector += `[imagesizes="${escapeSelectorAttributeValueInsideDoubleQuotes(options.imageSizes,)}"]`;}} else {preloadSelector += `[href="${escapeSelectorAttributeValueInsideDoubleQuotes(href,)}"]`;}} else {// 对于非图片类型的资源,直接向选择器中添加 href 属性值。preloadSelector += `[href="${escapeSelectorAttributeValueInsideDoubleQuotes(href,)}"]`;}let key = preloadSelector;switch (as) {case 'style':// 当资源类型为 style 时,将 key 更新为 getStyleKey(href) 的返回值key = getStyleKey(href);break;case 'script':// 当资源类型为 script 时,将 key 更新为 getScriptKey(href) 的返回值key = getScriptKey(href);break;}if (!preloadPropsMap.has(key)) {// 创建预加载属性const preloadProps = Object.assign(({rel: 'preload',href:as === 'image' && options && options.imageSrcSet ? undefined : href,as,}: PreloadProps),options,);preloadPropsMap.set(key, preloadProps);if (null === ownerDocument.querySelector(preloadSelector)) {if (as === 'style' &&ownerDocument.querySelector(getStylesheetSelectorFromKey(key))) {// 若资源类型为 style 且已存在对应样式表(通过 getStylesheetSelectorFromKey(key) 检查),则返回,不进行预加载。// We already have a stylesheet for this key. We don't need to preload it.return;} else if (as === 'script' &&ownerDocument.querySelector(getScriptSelectorFromKey(key))) {// 若资源类型为 script 且已存在对应脚本(通过 getScriptSelectorFromKey(key) 检查),则返回,不进行预加载。// We already have a stylesheet for this key. We don't need to preload it.return;}// 创建link元素const instance = ownerDocument.createElement('link');// 设置初始属性setInitialProperties(instance, 'link', preloadProps);// 标记可提升markNodeAsHoistable(instance);// 往head标签中插入子节点(ownerDocument.head: any).appendChild(instance);}}}
}
API之 preloadModule
preloadModule – React 中文文档
preloadModule
可以急切地预获取期望使用的 ESM 模块。
preloadModule("https://example.com/module.js", {as: "script"});
参考语法
preloadModule(href, options)
参数
- href:字符串,要下载的资源的 URL。
- options:对象,可以包含以下属性:
as
:必需的字符串,表示资源的类型,可能的值 包括 audio、document、embed、fetch、font、image、object、script、style、track、video 与 worker。crossOrigin
:字符串,表示要使用的 CORS 策略,可能的值为 anonymous 与 use-credentials。当 as 设置为 "fetch" 时是必需的。integrity
:字符串,为资源的加密哈希,用于 验证其真实性。nonce
:字符串,表示使用严格内容安全策略时允许资源的 加密随机数。
一、使用示范
import { preloadModule } from 'react-dom';function CallToAction() {const onClick = () => {preloadModule("https://example.com/module.js", {as: "script"});startWizard();}return (<button onClick={onClick}>Start Wizard</button>);
}
二、源码
function preloadModule(href: string, options?: ?PreloadModuleOptions) {if (typeof href === 'string') {if (options) {const crossOrigin = getCrossOriginStringAs(options.as,options.crossOrigin,);ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */.m(/* preloadModule */ href, {as:typeof options.as === 'string' && options.as !== 'script'? options.as: undefined,crossOrigin,integrity:typeof options.integrity === 'string'? options.integrity: undefined,});} else {ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */.m(/* preloadModule */ href);}}}
ReactDOMSharedInternals.d.m
preloadModule
函数用于预加载 ES6 模块资源,通过创建 rel="modulepreload"
的 link
元素来实现。它会根据资源类型(as
)和相关选项生成合适的选择器和属性,检查资源是否已存在于文档中,若不存在则插入新的 link
元素进行预加载。
function preloadModule(href: string, options?: ?PreloadModuleImplOptions) {previousDispatcher.m(/* preloadModule */ href, options);// 获取document对象const ownerDocument = getGlobalDocument();if (ownerDocument && href) {const as =options && typeof options.as === 'string' ? options.as : 'script';// 生成预加载选择器 preloadSelector,包含 rel="modulepreload"、资源类型 as 和资源链接 href。const preloadSelector = `link[rel="modulepreload"][as="${escapeSelectorAttributeValueInsideDoubleQuotes(as,)}"][href="${escapeSelectorAttributeValueInsideDoubleQuotes(href)}"]`;let key = preloadSelector;switch (as) {case 'audioworklet':case 'paintworklet':case 'serviceworker':case 'sharedworker':case 'worker':case 'script': {key = getScriptKey(href);break;}}if (!preloadPropsMap.has(key)) {const props: PreloadModuleProps = Object.assign(({rel: 'modulepreload',href,}: PreloadModuleProps),options,);preloadPropsMap.set(key, props);if (null === ownerDocument.querySelector(preloadSelector)) {switch (as) {case 'audioworklet':case 'paintworklet':case 'serviceworker':case 'sharedworker':case 'worker':case 'script': {if (ownerDocument.querySelector(getScriptSelectorFromKey(key))) {return;}}}const instance = ownerDocument.createElement('link');setInitialProperties(instance, 'link', props);markNodeAsHoistable(instance);(ownerDocument.head: any).appendChild(instance);}}}
}
工具函数之 getCrossOriginStringAs
返回值只有三种情况:use-credentials、空字符串、undefined。
function getCrossOriginStringAs(as: ?string,// 资源类型input: ?string,// crossorigin属性值
): ?CrossOriginString {// 字体类型返回空字符串if (as === 'font') {return '';}if (typeof input === 'string') {// 如果crossorigin值为use-credentials,否则返回空字符串return input === 'use-credentials' ? input : '';}return undefined;
}
工具函数之 getCrossOriginString
返回值只有三种情况:use-credentials、空字符串、undefined。
function getCrossOriginString(input: ?string): ?CrossOriginString {if (typeof input === 'string') {return input === 'use-credentials' ? input : '';}return undefined;
}
工具函数之 getGlobalDocument
获取document对象。
const globalDocument = typeof document === 'undefined' ? null : document;function getGlobalDocument(): ?Document {return globalDocument;
}
工具函数之 getResourcesFromRoot
获取资源,当资源不存在时进行初始化操作后返回。
function getResourcesFromRoot(root: HoistableRoot): RootResources {// 获取资源let resources = (root: any)[internalRootNodeResourcesKey];if (!resources) {// 设置资源resources = (root: any)[internalRootNodeResourcesKey] = {hoistableStyles: new Map(),hoistableScripts: new Map(),};}return resources;
}const internalRootNodeResourcesKey = '__reactResources$' + randomKey;
export type HoistableRoot = Document | ShadowRoot;
export type HoistableRoot = Document | ShadowRoot;
export type RootResources = {hoistableStyles: Map<string, StyleResource>,hoistableScripts: Map<string, ScriptResource>,
};
工具函数之 markNodeAsHoistable
设置节点为可提升。
function markNodeAsHoistable(node: Node) {(node: any)[internalHoistableMarker] = true;
}const internalHoistableMarker = '__reactMarker$' + randomKey;
工具函数之 getStyleKey
function getStyleKey(href: string) {const limitedEscapedHref =escapeSelectorAttributeValueInsideDoubleQuotes(href);return `href="${limitedEscapedHref}"`;
}
工具函数之 getScriptKey
function getScriptKey(src: string): string {const limitedEscapedSrc = escapeSelectorAttributeValueInsideDoubleQuotes(src);return `[src="${limitedEscapedSrc}"]`;
}
工具函数之 escapeSelectorAttributeValueInsideDoubleQuotes
// 正则表达式用于匹配字符串中的换行符(\n)、双引号(")和反斜杠(\\)。g 标志表示全局匹配
const escapeSelectorAttributeValueInsideDoubleQuotesRegex = /[\n\"\\]/g;function escapeSelectorAttributeValueInsideDoubleQuotes(value,
) {return value.replace(escapeSelectorAttributeValueInsideDoubleQuotesRegex,ch => '\\' + ch.charCodeAt(0).toString(16) + ' ',);
}
const input = 'This is a string with "quotes" and \n newlines and \\ backslashes.';
const escaped = escapeSelectorAttributeValueInsideDoubleQuotes(input);
console.log(escaped);
// This is a string with \22 quotes\22 and \a newlines and \5c backslashes.
工具函数之 getStylesheetSelectorFromKey
function getStylesheetSelectorFromKey(key: string) {return `link[rel="stylesheet"][${key}]`;
}
工具函数之 insertStylesheet
insertStylesheet
函数的主要作用是将样式元素(link
或 style
)按照特定的优先级规则插入到文档中。它会根据元素的 data-precedence
属性值来确定插入位置,确保相同优先级的样式元素相邻排列,并且按照优先级从高到低的顺序排列在文档中。
function insertStylesheet(instance: Element,precedence: string,// 优先级root: HoistableRoot,
): void {// 使用 querySelectorAll 查找根节点 root 下所有带有 data-precedence 属性的样式元素(包括 link 和 style)。const nodes = root.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]',);// 最后一个const last = nodes.length ? nodes[nodes.length - 1] : null;let prior = last;for (let i = 0; i < nodes.length; i++) {const node = nodes[i];// 获取优先级const nodePrecedence = node.dataset.precedence;// 如果当前元素的 data-precedence 与目标优先级 precedence 相同,则更新 prior 为该元素。if (nodePrecedence === precedence) {prior = node;} else if (prior !== last) {// 退出循环break;}}if (prior) {// 新元素插入到 prior 的下一个兄弟节点之前((prior.parentNode: any): Node).insertBefore(instance, prior.nextSibling);} else {const parent =root.nodeType === DOCUMENT_NODE// 将元素插入到文档的 head 中作为第一个子元素? ((((root: any): Document).head: any): Element)// 插入到 Shadow DOM 的根节点中作为第一个子元素: ((root: any): ShadowRoot);parent.insertBefore(instance, parent.firstChild);}
}
相关文章:
React19源码系列之 API(react-dom)
API之 preconnect preconnect – React 中文文档 preconnect 函数向浏览器提供一个提示,告诉它应该打开到给定服务器的连接。如果浏览器选择这样做,则可以加快从该服务器加载资源的速度。 preconnect(href) 一、使用例子 import { preconnect } fro…...
鸿蒙Next开发 获取APP缓存大小和清除缓存
1. 鸿蒙Next开发 获取APP缓存大小和清除缓存 1.1. 介绍 1.1.1. 文件系统分类 在最新的Core File Kit套件中,按文件所有者的不同。分为如下三类: (1)应用文件:文件所有者为应用,包括应用安装文件、应用…...
PNG转ico图标(支持圆角矩形/方形+透明背景)Python脚本 - 随笔
摘要 在网站开发或应用程序设计中,常需将高品质PNG图像转换为ICO格式图标。本文提供一份基于Pillow库实现的,能够完美保留透明背景且支持导出圆角矩形/方形图标的格式转换脚本。 源码示例 圆角方形 from PIL import Image, ImageDraw, ImageOpsdef c…...
『大模型笔记』Langchain作者Harrison Chase专访:环境智能体与全新智能体收件箱
Langchain作者Harrison Chase专访:环境智能体与全新智能体收件箱 文章目录 摘要访谈内容什么环境智能体为什么要探索环境智能体怎么让人类能更方便地和环境智能体互动参考文献摘要 LangChain 的 CEO Harrison Chase 提出了_“环境智能体”(Ambient Agents)的概念,这是一种…...
GPT( Generative Pre-trained Transformer )模型:基于Transformer
GPT是由openAI开发的一款基于Transformer架构的预训练语言模型,拥有强大的生成能力和多任务处理能力,推动了自然语言处理(NLP)的快速发展。 一 GPT发展历程 1.1 GPT-1(2018年) 是首个基于Transformer架构…...
游戏引擎学习第275天:将旋转和剪切传递给渲染器
回顾并为今天的内容定下基调 我们认为在实现通用动画系统之前,先学习如何手写动画逻辑是非常有价值的。虽然加载和播放预设动画是合理的做法,尤其是在团队中有美术人员使用工具制作动画的情况下更是如此,但手动编写动画代码能让我们更深入理…...
conda 输出指定python环境的库 输出为 yaml文件
conda 输出指定python环境的库 输出为 yaml文件。 有时为了项目部署,需要匹配之前的python环境,需要输出对应的python依赖库。 假设你的目标环境名为 myenv,运行以下命令: conda env export -n myenv > myenv_environment.ym…...
ES6 语法
扩展运算符 … 口诀:三个点,打散数组,逐个放进去 例子: let arr [1, 2];let more [3, 4];arr.push(...more); // arr 变成 [1, 2, 3, 4]解构赋值 口诀:左边是变量,右边是值,一一对应 例子&…...
BFS算法篇——打开智慧之门,BFS算法在拓扑排序中的诗意探索(下)
文章目录 引言一、课程表1.1 题目链接:https://leetcode.cn/problems/course-schedule/description/1.2 题目分析:1.3 思路讲解:1.4 代码实现: 二、课程表||2.1 题目链接:https://leetcode.cn/problems/course-schedul…...
While语句数数字
import java.util.Scanner;public class Hello {public static void main(String[] args) {Scanner in new Scanner(System.in);int number in.nextInt();int count 0;while( number > 0 ){number number / 10;count count 1;}System.out.println(count);} }...
G1JVM内存分配机制详解
为什么堆内存不是预期的3G? 当您设置-XX:MaxRAMPercentage75时,JVM并不会简单地将容器内存(4G)的75%全部分配给堆,原因如下: 计算基准差异: 百分比是应用于"可用物理内存"而非"容器总内存" &q…...
“端 - 边 - 云”三级智能协同平台的理论建构与技术实现
摘要 随着低空经济与智能制造的深度融合,传统集中式云计算架构在实时性、隐私保护和资源效率上的瓶颈日益凸显。本文提出“端 - 边 - 云”三级智能协同平台架构,以“时空 - 资源 - 服务”三维协同理论为核心,构建覆盖终端感知、边缘计算、云端…...
【UAP】《Empirical Upper Bound in Object Detection and More》
Borji A, Iranmanesh S M. Empirical upper bound in object detection and more[J]. arXiv preprint arXiv:1911.12451, 2019. arXiv-2019 文章目录 1、Background and Motivation2、Related Work3、Advantages / Contributions4、Experimental Setup4.1、Benchmarks Dataset…...
Web Service及其实现技术(SOAP、REST、XML-RPC)介绍
一.概述 1.Web Service(Web 服务) Web Service 由万维网联盟 (W3C) 定义为一种软件系统,旨在支持通过网络进行可互操作的计算机间交互。 广义概念:基于 Web 技术(如 HTTP 协议)的跨平台、跨语言通信机制…...
基于Spring Boot+Layui构建企业级电子招投标系统实战指南
一、引言:重塑招投标管理新范式 在数字经济浪潮下,传统招投标模式面临效率低、透明度不足、流程冗长等痛点。本文将以Spring Boot技术生态为核心,融合Mybatis持久层框架、Redis高性能缓存及Layui前端解决方案,构建一个覆盖招标代理…...
【嵌入式】记一次解决VScode+PlatformIO安装卡死的经历
PlatformIO 是开源的物联网开发生态系统。提供跨平台的代码构建器、集成开发环境(IDE),兼容 Arduino,ESP8266和mbed等。 开源库地址:https://github.com/platformio 在 VScode 中配置 PlatformIO 插件,记录…...
抗量子计算攻击的数据安全体系构建:从理论突破到工程实践
在“端 - 边 - 云”三级智能协同理论中,端 - 边、边 - 云之间要进行数据传输,网络的安全尤为重要,为了实现系统总体的安全可控,将构建安全网络。 可先了解我的前文:“端 - 边 - 云”三级智能协同平台的理论建构与技术实…...
【FMMT】基于模糊多模态变压器模型的个性化情感分析
遇到很难的文献看不懂,不应该感到气馁,应该激动,因为外审估计也看不太懂,那么学明白了可以吓唬他 缺陷一:输入依赖性与上下文建模不足 缺陷描述: 传统自注意力机制缺乏因果关系,难以捕捉序列历史背景多模态数据间的复杂依赖关系未被充分建模CNN/RNN类模型在…...
力扣Hot100(Java版本)
1. 哈希 1.1 两数之和 题目描述: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案,并且你不能使用两次相同…...
Stream流简介、常用方法
Stream流的三类方法 获取Stream流 创建一条流水线,并把数据放到流水线上准备进行操作 中间方法 流水线上的操作一次操作完毕之后,还可以继续进行其他操作 终结方法 一个Stream流只能有一个终结方法是流水线上的最后一个操作 生成Stream流的方式 Collec…...
C# 集成 FastDFS 完整指南
1. 环境准备 (1) 安装 FastDFS 服务端 部署 Tracker 和 Storage 节点,确保服务正常运行。 配置 tracker_server 地址(如 192.168.1.100:22122)。 (2) 添加 NuGet 包 通过 NuGet 安装 FastDFS 客户端库: Install-Pack…...
重构门店网络:从“打补丁“到“造地基“的跨越
您是否遇到过这样的窘境? 新店开张要等一周,就为装根网线; 偏远地区门店三天两头断网,顾客排长队却结不了账; 总部想看实时数据,结果收到一堆乱码报错; 总部ERP系统升级,2000家门…...
TI的ADS1291代替芯片LH001-99
血管疾病严重威胁人类生命健康安全,随着人口老龄化进程的加快和社会压力等因素的增加,患病率正呈现逐年上升趋势,并且越来越年轻化。然而,心血管疾病大多由器官器质性病变引起,一旦患病很难完全康复,需要进…...
NPOI 操作 Word 文档
管理 NuGet 程序包 # word操作 NPOI# 图片操作 SkiaSharp Controller代码 using Microsoft.AspNetCore.Mvc; using NPOI.Util; using NPOI.XWPF.Model; using NPOI.XWPF.UserModel; using SkiaSharp;namespace WebApplication2.Controllers {[Route("api/Npoi/[action]…...
css3基于伸缩盒模型生成一个小案例
css3基于伸缩模型生成一个小案例 在前面学习了尚硅谷天禹老师的css3内容后,基于伸缩盒模型做的一个小案例,里面使用了 flex 布局,以及主轴切换,以及主轴平分等特性,分为使用css3 伸缩盒模型方式,已经传统的…...
精简大语言模型:用于定制语言模型的自适应知识蒸馏
Streamlining LLMs: Adaptive Knowledge Distillation for Tailored Language Models 发表:NAACL 2025 机构:德国人工智能研究中心 Abstract 诸如 GPT-4 和 LLaMA-3 等大型语言模型(LLMs)在多个行业展现出变革性的潜力…...
Rollup入门与进阶:为现代Web应用构建超小的打包文件
我们常常面临Webpack复杂配置或是Babel转译后的冗余代码,结果导致最终的包体积居高不下加载速度也变得异常缓慢,而在众多打包工具中Rollup作为一个轻量且高效的选择,正悄然改变着这一切,本文将带你深入了解这个令人惊艳的打包工具…...
博客系统技术需求文档(基于 Flask)
以下内容是AI基于要求生成的技术文档,仅供参考~ 🧱 一、系统架构设计概览 层级 内容 前端层 HTML Jinja2 模板引擎,集成 Markdown 编辑器、代码高亮 后端层 Flask 框架,RESTful 风格,Jinja2 渲染 数据库 SQLi…...
快速排序、归并排序、计数排序
文章目录 前言一、归并排序算法逻辑递归实现非递归实现 二、快速排序算法介绍递归实现非递归实现算法的一种优化—三路划分法 四、计数排序算法原理代码实现优劣分析 五、排序算法的性能比较总结 前言 本文介绍这三种非常强大的排序算法,每种算法都有各自的特点、不…...
python语言与地理处理note 2025/05/11
1. 函数定义必须要在调用之前 (1)正确示例: def test():print("what a wonderful world!")test() (2)错误示例: test() def test():print("what a wonderful world!") 会报错&…...
贪心算法:最小生成树
假设无向图为: A-B:1 A-C:3 B-C:1 B-D:4 C-D:1 C-E:5 D-E:6 一、使用Prim算法: public class Prim {//声明了两个静态常量,用于辅助 Prim 算法的实现private static final int V 5;//点数private static final int INF Integer.MA…...
免费 OCR 识别 + 批量处理!PDF 工具 提升办公效率
各位办公小能手们!今天给你们介绍一款超厉害的软件——PDF工具V2.2!我跟你们说,这玩意儿就像是PDF界的超级英雄,专门搞定PDF文件的编辑、转换、压缩这些事儿。 先说说它的核心功能哈。基础文档管理方面,它能把好几个PD…...
尼康VR镜头防抖模式NORMAL和ACTIVE的区别(私人笔记)
1. NORMAL 模式(常规模式) 适用场景:一般手持拍摄,比如人像、静物、风景或缓慢平移镜头(如水平追拍)等。工作特性: 补偿手抖引起的小幅度震动(比如手持时自然的不稳)&am…...
在scala中sparkSQL读入csv文件
以下是 Scala 中使用 Spark SQL 读取 CSV 文件的核心步骤和代码示例(纯文本): 1. 创建 SparkSession scala import org.apache.spark.sql.SparkSession val spark SparkSession.builder() .appName("Spark SQL Read CSV") …...
swift flask python ipad当电脑键盘 实现osu x键和z键 长按逻辑有问题 quart 11毫秒
键盘不行我5星都打不过,磁轴不在身边 127.0.0.1不行要用192.168哪个地址 from flask import Flask from pynput.keyboard import Controller from threading import Threadapp Flask(__name__) keyboard Controller()# 按下按键 app.route("/press_down/<…...
浅论3DGS溅射模型在VR眼镜上的应用
摆烂仙君小课堂开课了,本期将介绍如何手搓VR眼镜,并将随手拍的电影变成3D视频。 一、3DGS模型介绍 3D 高斯模型是基于高斯函数构建的用于描述三维空间中数据分布概率的模型,高斯函数在数学和物理领域有着广泛应用,其在 3D 情境下…...
React状态管理-对state进行保留和重置
相同位置的相同组件会使得 state 被保留下来 当你勾选或清空复选框的时候,计数器 state 并没有被重置。不管 isFancy 是 true 还是 false,根组件 App 返回的 div 的第一个子组件都是 <Counter />: 你可能以为当你勾选复选框的时候 st…...
嵌入式STM32学习——外部中断EXTI与NVIC的基础练习⭐
按键控制LED灯 按键控制LED的开发流程: 第一步:使能功能复用时钟 第二布,配置复用寄存器 第三步,配置中断屏蔽寄存器 固件库按键控制LED灯 外部中断EXTI结构体:typedef struct{uint32_t EXTI_Line; …...
git merge和git rebase
git merge和git rebase 在Git中merge和rebase都是git在管理整合分支的两种主要工具,但是他们的工作方式、提交历史影响和使用场景不同。 git merge 定义 将两个分支的提交历史合并,创建一个新的合并提交(merge commit)ÿ…...
我的MCP相关配置记录
1.VSCode的Cline中的MCP {"mcpServers": {"github.com/modelcontextprotocol/servers/tree/main/src/github": {"autoApprove": [],"disabled": false,"timeout": 60,"command": "cmd","args&quo…...
浅聊一下数据库的索引优化
背景 这里的索引说的是关系数据库(MSSQL)中的索引。 本篇不是纯技术性的内容,只是聊一次性能调优的经历,包含到一些粗浅的实现和验证手段,所以,大神忽略即可。 额…对了,笔者对数据库的优化手段…...
如何创建maven项目
1.IDEA 中创建 Maven 项目 步骤一:点击 File -> New -> Project,在弹出的窗口左侧选择 Maven,点击 Next: 步骤二:填写项目的 GroupId、ArtifactId、Version 等信息(这些对应 pom.xml 中的关键配置&am…...
LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS
一、引言 在自然语言处理领域,大规模预训练语言模型(LLMs)展现出强大的语言理解和生成能力。然而,将这些模型适配到多个下游任务时,传统微调方法面临诸多挑战。LoRA(Low-Rank Adaptation of Large Language Models)作为一种创新的微调技术,旨在解决这些问题,为大语言…...
Conda在powershell终端中无法使用conda activate命令
主要有以下原因: Windows PowerShell安全策略:默认情况下,PowerShell的执行策略设置为"Restricted",这会阻止运行脚本,包括conda的初始化脚本。调用方式不同:在PowerShell中,需要使用…...
MySQL索引底层数据结构与算法
1、索引的数据结构 1.1、二叉树 1.2、红黑树(二叉平衡树) 1.3、hash表 对key进行一次hash计算就可以定位出数据存储的位置 问题:hash冲突问题、仅满足和in的查找,不支持范围查找 1.4、B-tree 1.5、B tree 非叶子节点不存储data&…...
GOOSE 控制块参数gocbRef及goID有大小写要求
在 IEC 61850 标准中,GOOSE 控制块参数gocbRef和goID的大小写是严格区分的。这一结论基于以下多维度分析: 一、标准协议与配置文件的强制性 XML 语法的刚性约束 GOOSE 控制块的配置信息通过 SCL(Substation Configuration Languageÿ…...
重庆医科大学附属第二医院外科楼外挡墙自动化监测
1.项目概述 重庆医科大学附属第二医院,重医附二院,是集医疗、教学、科研、预防保健为一体的国家三级甲等综合医院。前身为始建于1892年的“重庆宽仁医院”。医院现有开放床位 1380张,年门诊量超过百万人次,年收治住院病人4.5万人…...
3.4 数字特征
本章系统讲解随机变量的数字特征理论,涵盖期望、方差、协方差与相关系数的核心计算与性质。以下从四个核心考点系统梳理知识体系: 考点一:期望(数学期望) 1. 离散型随机变量的数学期望 一维情形: E ( X …...
servlet-api
本次内容总结 1、再次学习Servlet的初始化方法 2、学习Servlet中的ServletContext和<context-param> 3、什么是业务层 4、IOC 5、过滤器 7、TransActionManager、ThreadLocal、OpenSessionInViewFilter 1、再次学习Servlet的初始化方法 1)Servlet生命周期&…...
NLTK进行文本分类和词性标注
《python ⾃然语⾔处理实战》学习笔记 NLTK 下载依赖 !pip install nltkimport nltk nltk.download(punkt_tab)分词(tokenize) from nltk.tokenize import word_tokenize from nltk.text import Textinput_str """Twinkle, twinkle, little star, How I won…...