ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

wp-calypso 数据查询组件深度解析:QuerySiteProducts 站点产品数据获取实战指南

wp-calypso 数据查询组件深度解析:QuerySiteProducts 站点产品数据获取实战指南 前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载QuerySiteProducts /是 WordPress.com 前端应用 wp-calypso 中负责站点Site级产品Product数据网络请求管理的 React 组件。它遵循该系列组件声明式数据获取的设计哲学渲染组件即触发请求数据落地 Redux 全局状态树后由业务组件按需读取。读完本文你将掌握该组件的使用姿势、背后完整的 action → reducer → selector 数据流链路以及它在套餐/定价页面的真实调用场景可直接在项目中复刻同样的数据获取模式。组件定位与设计思想wp-calypso 的client/components/data/目录下维护着一大批以query-前缀命名的查询组件query-site-products是其中之一。这类组件的共同特点是声明式触发请求不需要在业务组件里手写useEffect加 Redux dispatch 样板代码只要把组件渲染出来请求就会自动发起无渲染renderless不接收 children也不渲染任何 DOM 元素只负责发出请求这一个副作用幂等防重内部通过 selector 判断该站点是否已在请求中避免重复发起相同的网络请求。组件的官方定位README表述为QuerySiteProducts /是一个用于管理站点特定产品数据网络请求的 React 组件。快速上手最小可用示例根据 query-site-products 的 README组件的唯一必需参数是siteIdimport QuerySiteProducts from calypso/components/data/query-site-products; export default function MyPlansPage( { selectedSiteId } ) { return ( div {/* 渲染即触发 /sites/:siteId/products 请求 */} QuerySiteProducts siteId{ selectedSiteId } / {/* 其余业务 UI…… */} /div ); }组件对外暴露的 props 契约非常简单见 index.jsx 末尾的propTypes声明Prop类型是否必填说明siteIdnumber必填业务上要求目标站点的 ID为空时不发请求siteId为undefined、null或0时请求函数会直接短路返回不会触发任何网络调用——这一点由源码中的守卫条件保证。组件内部实现解析query-site-products/index.jsx 的实现只有 21 行却完整呈现了 wp-calypso 查询组件的标准写法const request ( siteId ) ( dispatch, getState ) { if ( siteId ! isRequestingSiteProducts( getState(), siteId ) ) { dispatch( fetchSiteProducts( siteId ) ); } }; export default function QuerySiteProducts( { siteId } ) { const dispatch useDispatch(); useEffect( () { dispatch( request( siteId ) ); }, [ dispatch, siteId ] ); return null; }拆解其中三个关键设计thunk 形式的请求函数request返回一个接收dispatch与getState的 thunk。这里巧妙地利用了dispatch thunk 时 getState 可用的特性在派发 action 之前先读取当前 Redux 状态实现请求去重——若isRequestingSiteProducts( state, siteId )已为真该站点产品正在请求中则直接放弃本次请求。Hooks 驱动useEffect的依赖数组为[ dispatch, siteId ]。当siteId变化如用户切换站点时会重新触发请求dispatch来自 Redux 的useDispatch引用稳定不会造成多余重跑。返回null组件不渲染任何 DOM 元素符合无渲染查询组件的定位。底层数据流State / Sites / Products 模块组件只是数据流的入口真正处理数据的是 client/state/sites/products 模块。该模块官方 README 将其定位为 A module for managing site products data管理站点产品数据的模块完整链路如下QuerySiteProducts │ useEffect dispatch ▼ fetchSiteProducts( siteId ) ← actions.js发 GET /sites/:siteId/products │ ▼ SITE_PRODUCTS_FETCH ← reducer 置 isRequesting: true SITE_PRODUCTS_FETCH_COMPLETED ← reducer 写入 data含 createSiteProductObject 归一化 SITE_PRODUCTS_FETCH_FAILED ← reducer 写入 error │ ▼ getProductsBySiteId / getAvailableProductsBySiteId / isRequestingSiteProducts ← selectors.js业务组件消费Action 层请求与响应归一化actions.js 暴露两个 action creatorfetchSiteProducts( siteId )核心请求入口。先派发SITE_PRODUCTS_FETCH标记请求开始再通过wpcom.req.get( \/sites/${ siteId }/products )调用 WordPress.com REST API。成功后派发SITE_PRODUCTS_FETCH_COMPLETED失败则派发SITE_PRODUCTS_FETCH_FAILED并带有兜底错误文案 There was a problem fetching site products. Please try again later or contact support.错误信息优先使用服务端返回的error.message。fetchSiteProductsCompleted( siteId, products )将 API 返回的产品对象整体写入 state。注意这里会经过mapValues( products, createSiteProductObject )做字段归一化。归一化逻辑见 assembler.jsexport const createSiteProductObject ( product ) { if ( ! product ) { return {}; } product.cost Number( product.cost ); product.tierUsage Number( product.price_tier_usage_quantity ); return product; };它把 API 返回的字符串型cost价格与price_tier_usage_quantity套餐档位用量统一转换为Number类型并重命名为语义化的tierUsage供前端做金额计算与用量展示。Reducer 层按站点隔离的状态结构reducer.js 以sites.products为挂载点每个站点一份独立状态初始结构为export const initialSiteState { data: null, // 产品数据归一化后的对象 error: null, // 最近一次请求的错误信息 hasLoadedFromServer: false, // 是否已成功加载过 isRequesting: false, // 是否正在请求中 };三种 action 对应的状态迁移Action状态变化SITE_PRODUCTS_FETCHerror清空、isRequesting: trueSITE_PRODUCTS_FETCH_COMPLETEDerror清空、hasLoadedFromServer: true、isRequesting: false、data写入产品对象SITE_PRODUCTS_FETCH_FAILEDerror写入错误信息、isRequesting: falseReducer 测试test/reducer.js覆盖了初始空状态、未知 action 不变性、请求中、请求失败、请求成功以及多站点状态累积等场景例如不同站点的产品数据会按 siteId 各自累积互不覆盖。Selector 层业务组件的消费入口selectors.js 提供四个常用查询函数Selector作用getProductsBySiteId( state, siteId )返回某站点完整的产品状态含isRequesting等元信息siteId为空时返回initialSiteStategetAvailableProductsBySiteId( state, siteId )在data上按product.available过滤只保留可购买产品isRequestingSiteProducts( state, siteId )判断某站点产品是否正在请求中QuerySiteProducts 的去重逻辑正依赖它getSiteAvailableProduct( state, siteId, productSlug )按产品 slug如jetpack_search精确取单个可购买产品getSiteAvailableProductCost( state, siteId, productSlug )快捷返回该产品的cost字段真实使用案例套餐与定价页面在 wp-calypso 中站点套餐/定价相关页面是 QuerySiteProducts 的主要消费方。以 my-sites/plans/current-plan/index.tsx 为例import QuerySiteProducts from calypso/components/data/query-site-products; // 组件渲染中 QuerySiteProducts siteId{ selectedSiteId } /此外my-sites/plans/jetpack-plans/selector.tsx、storage-pricing/index.tsx 与 upsell/index.tsx 也均引入了该组件。这印证了典型用法页面挂载时先渲染 QuerySiteProducts 触发产品数据拉取同时搭配 selectors 读取isRequesting/data渲染加载态与定价内容实现数据到位才展示、请求中去重的流畅体验。与其他 Query 组件的共性模式QuerySiteProducts只是 wp-calypsoclient/components/data/系列组件的一个代表。若你需要在项目中新增类似的站点数据查询组件如站点插件、站点订阅者等遵循同一套模板即可组件接收目标实体的 id 作为 prop内部用useEffectuseDispatch派发 thunkthunk 内先调用对应的isRequesting*selector 做防重判断网络层统一走wpcom.req成功后派发*_COMPLETEDactionstate 侧按 id 隔离数据配齐isRequesting/hasLoadedFromServer/error/data四元组提供get*与isRequesting*系列 selector 供业务消费。小结QuerySiteProducts /用极少的代码将站点产品数据的网络请求、去重、状态管理与消费完整串联起来业务侧一行QuerySiteProducts siteId{ id } /即可触发拉取数据经fetchSiteProducts→ reducer → selector 的标准化链路落入 Redux最终由套餐、定价等页面按需读取。理解这条链路也就掌握了 wp-calypso 声明式数据获取架构的通用范式可以直接迁移到其他 query 组件与业务场景中。赞分享前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载相关推荐wp-calypso 中 QueryJetpackProductInstallStatus 组件解析Jetpack 产品安装状态的数据查询实践wp calypso 中 QueryJetpackProductInstallStatus 组件解析Jetpack 产品安装状态的数据查询实践 QueryJ前端CMS深入解析 wp-calypso 的 QueryJetpackConnection /Jetpack 站点连接状态的声明式数据获取组件深入解析 wp calypso 的 QueryJetpackConnection / Jetpack 站点连接状态的声明式数据获取组件 导读 QueryJ前端CMSwp-calypso 主题数据查询组件 QueryCanonicalTheme多源归一的 canonical 主题数据获取机制解析wp calypso 主题数据查询组件 QueryCanonicalTheme多源归一的 canonical 主题数据获取机制解析 QueryCanonica前端CMS上一篇Roc 语言单引号字面量模式匹配以 s_quote_pattern 快照测试剖析编译器前端管线下一篇3分钟搞定Docker一键部署Casdoor开发者告别复杂配置创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表