前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载是 WordPress.com 桌面端/Web 应用WP Calypso中用于通过 WP.com 服务端发起 WHOIS 查询的轻量级 React 组件。本文将以 client/components/data/query-whois/README.md 为骨架结合组件实现、Redux action/reducer、selector 与真实业务调用场景完整还原渲染即查询、数据进 Redux、页面按需消费的数据预取模式帮助你理解并复用在 Calypso 中查询型数据组件的标准写法。组件定位无渲染、无子节点的数据预取器在 WP Calypso 中QueryWhois属于一组约定俗成的Query 组件data-fetching component。这类组件遵循统一的设计哲学只负责触发数据请求不负责渲染任何 UI不接受 children也不会渲染任何自身内容渲染组件本身即是一次副作用数据落地到全局 Redux 状态树后由页面上其它展示型组件通过 selector 消费。原文档对这一点给出了非常明确的定义README.mdQueryWhois /is a React component used to perform a WHOIS lookup via WP.com server-side. The queried domain must be owned by the user.其中有两个关键约束值得注意查询经由 WP.com 服务端完成即客户端不直接连接注册局 WHOIS 服务而是调用 WP.com 的 REST 接口由服务端代理查询被查询的域名必须归属于当前登录用户组件本身不校验所有权但服务端接口会在权限不足时拒绝请求。快速上手最小可用用法原文档给出的用法极其简洁——渲染组件并传入domain即可function MyComponent() { const domain example.com; return QueryWhois domain{ domain } /; }需要注意的细节组件返回null因此无论放在 JSX 树的哪个位置都不会产生额外 DOM 节点组件只接受一个 propdomain由于查询的是当前用户拥有的域名这里的domain通常是完整注册域名如example.com而非子域名或带协议头的 URL。在真实页面中它往往与其他 Query 组件并列渲染例如批量编辑联系信息页面同时拉取站点域名列表与 WHOIS 数据见下文实际业务场景。Props 契约唯一必需的domain组件的 propTypes 定义在 index.jsxQueryWhois.propTypes { domain: PropTypes.string.isRequired, };Prop类型必填说明domainstring是待查询 WHOIS 的域名必须归当前用户所有由于domain是必需 prop若未传入React 会在开发模式下给出 PropTypes 警告同时组件内部的请求函数也会因domain为空而跳过 dispatch见下文实现解析。组件源码逐行解析防重复请求与 effect 触发组件的完整实现在 client/components/data/query-whois/index.jsx全文仅 27 行核心逻辑如下import PropTypes from prop-types; import { useEffect } from react; import { useDispatch } from react-redux; import { requestWhois } from calypso/state/domains/management/actions; import isRequestingWhois from calypso/state/selectors/is-requesting-whois; const request ( domain ) ( dispatch, getState ) { if ( domain ! isRequestingWhois( getState(), domain ) ) { dispatch( requestWhois( domain ) ); } }; function QueryWhois( { domain } ) { const dispatch useDispatch(); useEffect( () { dispatch( request( domain ) ); }, [ dispatch, domain ] ); return null; }这段实现蕴含了几个重要设计依赖注入式 thunkrequest(domain)返回一个接收(dispatch, getState)的 Redux thunk把是否发起请求的决策权交给 thunk 内部而不是在组件里直接判断。双重防重空值防护domain为空时不发起请求进行中防护调用 selectorisRequestingWhois(getState(), domain)检查该域名是否已有请求正在进行避免重复请求同一域名。useEffect依赖数组[ dispatch, domain ]意味着domain变化时组件会重新触发查询dispatch引用稳定不会引起多余重跑。domain变为不同域名时会按新域名再次发起请求。渲染副作用分离组件恒返回null所有副作用都被收敛在 effect 中便于测试与复用。从源码结构看这也是整个 Calypso 中大量QueryXxx组件如QuerySiteDomains共同采用的标准模式组件壳 防重 thunk Redux action。Redux 数据流从组件渲染到状态落地QueryWhois只是链路的起点真正的网络请求发生在 action 层。dispatch 的requestWhois定义于 client/state/domains/management/actions.tsxexport function requestWhois( domain: string ) { return ( dispatch: CalypsoDispatch ) { dispatch( { type: DOMAIN_MANAGEMENT_WHOIS_REQUEST, domain, } ); return wpcom.req .get( /domains/${ domain }/whois ) .then( ( whoisData: WhoisData ) { dispatch( receiveWhois( domain, whoisData ) ); dispatch( { type: DOMAIN_MANAGEMENT_WHOIS_REQUEST_SUCCESS, domain, } ); } ) .catch( ( error: Error ) { dispatch( { type: DOMAIN_MANAGEMENT_WHOIS_REQUEST_FAILURE, domain, error, } ); } ); }; }完整流程如下渲染 QueryWhois domainexample.com / └─ useEffect → dispatch(request(domain)) ├─ isRequestingWhois(state, domain) 为 false 时放行 ├─ dispatch: DOMAIN_MANAGEMENT_WHOIS_REQUEST 标记请求中 ├─ wpcom.req.get(/domains/${domain}/whois) 服务端 WHOIS 查询 ├─ 成功 → DOMAIN_MANAGEMENT_WHOIS_RECEIVE写入数据 │ → DOMAIN_MANAGEMENT_WHOIS_REQUEST_SUCCESS清除请求中标记 └─ 失败 → DOMAIN_MANAGEMENT_WHOIS_REQUEST_FAILURE清除请求中标记并记录 error对应的 action type 常量集中在 client/state/action-types.tsDOMAIN_MANAGEMENT_WHOIS_RECEIVE DOMAIN_MANAGEMENT_WHOIS_REQUEST DOMAIN_MANAGEMENT_WHOIS_REQUEST_FAILURE DOMAIN_MANAGEMENT_WHOIS_REQUEST_SUCCESS DOMAIN_MANAGEMENT_WHOIS_SAVE DOMAIN_MANAGEMENT_WHOIS_SAVE_FAILURE DOMAIN_MANAGEMENT_WHOIS_SAVE_SUCCESS DOMAIN_MANAGEMENT_WHOIS_UPDATE这里可以观察到完整的查询/保存/更新生命周期除只读查询外saveWhois会通过POST /domains/${domain}/whois把修改后的联系信息写回注册局并可携带transfer_lock参数决定是否在更新后设置 60 天转移锁见 actions.tsx。QueryWhois负责的是其中查询这一半。状态管理reducer、schema 与 selectorReducer 结构WHOIS 相关的 Redux 状态由 client/state/domains/management/reducer.js 维护经combineReducers合并为三个子状态见 reducer.js#L116-L120export default combineReducers( { items, isRequestingWhois, isSaving, } );isRequestingWhois由keyedReducer(domain, ...)按域名分键DOMAIN_MANAGEMENT_WHOIS_REQUEST置为true成功/失败后复位为falsereducer.js#L15-L25。这正是QueryWhois防重逻辑读取的状态。items以域名为 key 缓存 WHOIS 数据对象经withSchemaValidation(domainWhoisSchema, ...)包裹做运行时校验收到DOMAIN_MANAGEMENT_WHOIS_RECEIVE时整体写入收到DOMAIN_MANAGEMENT_WHOIS_UPDATE时把新的注册人联系信息合并进对应记录reducer.js#L91-L114。isSaving记录保存请求的pending/success/error状态reducer.js#L34-L63。校验 Schema数据写入前会经过 client/state/domains/management/schema.js 定义的 JSON Schema 校验它刻画了 WHOIS 记录中联系信息字段的基本形态export const domainWhoisSchema { type: object, additionalProperties: true, patternProperties: { first_name: { type: string }, last_name: { type: string }, email: { type: string }, phone: { type: string }, address1: { type: string }, address2: { type: string }, city: { type: string }, state: { type: string }, postal_code: { type: string }, country_code: { type: string }, }, };Selector读取请求状态与数据请求状态client/state/selectors/is-requesting-whois.js 返回布尔值供组件做加载判断export default function isRequestingWhois( state, domain ) { return state?.domains?.management?.isRequestingWhois?.[ domain ] ?? false; }数据读取client/state/selectors/get-registrant-whois.js 从items中取出该域名的 WHOIS 记录数组再借助 client/lib/domains/whois/utils.js 中的findRegistrantWhois筛选出type registrant的注册人记录export default function getRegistrantWhois( state, domain ) { const whoisContacts state?.domains?.management?.items?.[ domain ] ?? []; return findRegistrantWhois( whoisContacts ); }WHOIS 记录的两种类型定义在 client/lib/domains/whois/constants.jsREGISTRANT注册人与PRIVACY_SERVICE隐私保护服务。响应数据结构WhoisData 契约服务端返回的完整 WHOIS 数据契约定义在 client/state/domains/management/types.ts主要字段如下字段类型含义typeregistration \| redirect \| mapping域名的注册类型verifiedboolean是否已验证lockedboolean是否被锁定转移锁maybe_pending_transferboolean是否可能存在待处理转移nameserversstring[]域名服务器列表whoisWhoisDataEntry注册人联系信息fname/lname/org/email/sa1/sa2/city/sp/pc/cc/phone/faxemailWhoisEmailRecord邮箱转发与 MX 服务器配置privacyfalse \| WhoisPrivacy隐私保护状态private/availabledns{ records: WhoisDnsRecord[] }DNS 记录列表sitenamestring站点名称注意WhoisDataEntry中的字段如fname、sa1与 schema 中使用的字段名如first_name、address1并不完全一致——前者是服务端返回的缩写命名后者是保存/展示时使用的完整命名。这是从源码结构中观察到的差异实际对接时需留意字段映射。实际业务场景两个真实消费方QueryWhois在 Calypso 中主要有两个典型调用场景它们共同验证了渲染即预取模式的价值。场景一ICANN 邮箱验证卡片在 client/my-sites/domains/domain-management/components/icann-verification/index.jsx 中当contactDetails注册人联系信息尚未从状态中取到时页面直接渲染QueryWhois触发拉取if ( ! contactDetails ) { return QueryWhois domain{ selectedDomainName } /; }该组件通过getRegistrantWhoisselector 消费数据拿到注册人邮箱后展示验证您的邮箱地址卡片并提供重新发送 ICANN 验证邮件的入口resendIcannVerification。场景二批量编辑联系信息页client/my-sites/domains/domain-management/edit-contact-info-page/bulk-edit-contact-info-page.tsx 是更复杂的用法用户从域名表格中勾选多个域名后进入批量编辑页组件对每一个选中的域名渲染一个QueryWhois并以域名作为key{ selectedDomains?.map( ( domain ) ( QueryWhois domain{ domain.domain } key{ domain.domain } / ) ) }同时页面通过isRequestingWhoisSelector轮询任一域名是否仍在请求中作为整页加载态isDataLoading的一部分bulk-edit-contact-info-page.tsx#L121-L132const isRequestingWhois useSelector( ( state: IAppState ) selectedDomains?.some( ( domain ) isRequestingWhoisSelector( state, domain.domain ) ) );这一场景展示了 Query 组件的两个扩展要点一对多预取通过map渲染多个实例每个域名独立触发请求key保证 React 复用/卸载逻辑正确请求态驱动 UI把多个域名的isRequestingWhois聚合起来控制骨架屏或占位符的显示避免用户看到未就绪的表单。最佳实践小结从QueryWhois的完整实现与消费方式中可以提炼出在 Calypso 中编写查询型数据组件的几条通用经验组件恒返回null把网络请求封装为 useEffect 副作用便于任意位置挂载在 thunk 内做防重判断isRequestingWhoisselector 空值检查避免多个页面实例对同一域名发起重复请求请求生命周期三段式REQUEST → RECEIVE/SUCCESS/FAILURE写入 Redux让加载中/成功/失败状态可被任意页面消费数据按域名分键缓存keyedReducer(domain)天然支持多域名场景与跨页面复用消费端使用 selector 而非直接访问 action保持状态读取路径统一如getRegistrantWhois、isRequestingWhois需要批量预取时用map渲染多个实例并指定稳定的key同时聚合请求态驱动页面加载 UI。若要深入阅读推荐按以下路径继续探索组件实现 index.jsx → action 定义 actions.tsx → reducer 与 schema reducer.js、schema.js → selectors is-requesting-whois.js、get-registrant-whois.js → 业务消费方 icann-verification/index.jsx 与 bulk-edit-contact-info-page.tsx。赞分享前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载相关推荐wp-calypso 中的 DomainManagementData基于 Redux 的容器组件数据预取模式实战解析wp calypso 中的 DomainManagementData基于 Redux 的容器组件数据预取模式实战解析 导读 DomainManagementD前端CMSwp-calypso 数据查询组件 QueryDomainInfo 源码解析域名的 WAPI 信息获取与状态管理实战指南wp calypso 数据查询组件 QueryDomainInfo 源码解析域名的 WAPI 信息获取与状态管理实战指南 QueryDomainInfo /前端CMS深入解析 wp-calypso 的 QueryJetpackConnection /Jetpack 站点连接状态的声明式数据获取组件深入解析 wp calypso 的 QueryJetpackConnection / Jetpack 站点连接状态的声明式数据获取组件 导读 QueryJ前端CMS创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
河北知名的火花机服务商实力公司推荐 选火花机别踩坑!4个高频痛点先理清在机械加工、模具制造这类行业里,火花机几乎是刚需设备,但不少企业在选购和使用时都踩过不少坑。
踩坑1:盲目选高配机型
不少老板看参数时只看最高精度最大加工范围,觉得买贵的准没错,… · 2026/9/25 3:26:24
Proteus 8仿真STM32全攻略:从安装到调试避坑指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 3:26:24
IronClaw Live Canary 回归矩阵:本地运行、账号体系与 CI 集成完全指南 人工智能AI 应用交互助手AI Agent 【免费下载链接】ironclaw IronClaw is an Agent OS focused on privacy, security and extensibility 项目地址: https://gitcode.com/gh_mirrors/iro/ironclaw 点击查看 免费下载 IronClaw 的 live canary 是一套面向真实第三方… · 2026/9/25 3:26:18
CodeGuide 拼团交易平台:从 MRD 到 PRD 的拼团需求分析全流程解析 文档教程后端 【免费下载链接】CodeGuide :books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总,旨在为大家提供一个清晰详细的学习教程,侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助,请给予支持(关注、… · 2026/9/25 3:56:51
OrangePi 5 Plus 构筑双 EtherCAT 与 6 路 CAN 软实时主站实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 3:56:51
C++智能指针循环引用:weak_ptr原理与内存泄漏排查实战 排查了大半天的内存泄漏,最后发现根源是两个shared_ptr互相引用——这类循环引用问题,可以说是 C 智能指针领域最经典的坑之一。今天这篇把weak_ptr解决shared_ptr循环引用的来龙去脉完整梳理一遍:底层原理、引用计数到底在数什么、实际改造手… · 2026/9/25 3:56:45
Buildah pull 命令完全指南:镜像拉取的传输协议、认证配置与拉取策略详解 云原生 【免费下载链接】buildah A tool that facilitates building OCI images. 项目地址: https://gitcode.com/gh_mirrors/bu/buildah 点击查看 免费下载 Buildah 是构建 OCI 镜像的实用工具,buildah pull 是其核心命令之一,负责按照指定… · 2026/9/25 3:56:45
RocketMQ大消息处理实战:4MB限制排查与优化方案 1. 4MB限制不是传说:客户端和Broker各卡一道,先搞清楚“谁说了算”上周有个同事跑来找我,说线上给下游推送客户画像消息,突然开始报错,后台一看发送端直接抛了MQClientException: message body size over maxMessageSi… · 2026/9/25 3:56:33
OpenShorts AI布局自动决策的秘密:为什么发12帧比发整个视频更聪明(含成本测算) OpenShorts AI布局自动决策的秘密:为什么发12帧比发整个视频更聪明(含成本测算) 【免费下载链接】openshorts Open source AI clip generator: turns long videos into viral 9:16 shorts with AI moment detection, face tracking, subtitle… · 2026/9/25 3:56:27
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37