ARTICLE DETAIL

资讯详情

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

wp-calypso 主题模块深入解析:Theme Showcase 架构、操作定义与多站点视图实现

wp-calypso 主题模块深入解析:Theme Showcase 架构、操作定义与多站点视图实现 前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载导读本文基于 wp-calypso 仓库 client/my-sites/themes/README.md 展开系统梳理 WordPress.com 主题展示Theme Showcase模块的目录职责、核心组件与状态逻辑。该模块承载/themes路由需要同时处理多站点multi-site、单站点single-site与 Jetpack 站点三类视图并支撑主题的激活、定制、预览、购买、订阅等操作。读完本文你将掌握该模块的文件组织方式、主题操作选项Theme Options的定义与动态显隐机制、搜索与筛选的 URL 构造规则以及 WP.com 与 WP.org 主题结果的混合排序算法可直接对照源码继续深入或在此基础上扩展新功能。模块定位服务于/themes的 Theme Showcase根据 README.md 的定义client/my-sites/themes/目录负责渲染 Theme Showcase它位于/themes路由下并处理三种视图多站点视图multi-site用户拥有多个站点但尚未选定站点时展示全局主题库操作入口如激活会引导用户先选择站点单站点视图single-site已选定某个 WordPress.com 站点主题操作直接作用于该站点Jetpack 站点视图针对通过 Jetpack 连接的站点逻辑上有一系列差异例如个别主题购买、Premium 主题激活需要升级 Jetpack 套餐等见下文theme-options.js中各hideForTheme判定。从当前源码结构看模块内文件已经过多次演进README 中提及的若干文件与现在仓库中的实际组件存在对应关系下文会逐一标注README 提及文件当前仓库对应实现职责main.jsxtheme-showcase.jsx controller.jsx主题模块主父组件 / 路由控制器thanks-modal.jsxactivation-modal.tsx主题激活后的确认对话框theme-search-cardclient/components/search-themes/index.tsxShowcase 搜索栏helpers.jshelpers.js辅助函数URL 构造、插序、埋点theme-options.jstheme-options.js主题操作选项定义themes-selection.jsxthemes-selection.jsx组合搜索框与主题列表的大组件路由注册与 SSR 数据预取位于 controller.jsx 与 controller-logged-in.jsx入口文件为 index.web.js 与 index.node.js。theme-options.js主题操作选项的完整定义theme-options.js 是 README 重点介绍的文件它集中定义了用户对某个主题可执行的所有操作选项例如Activate激活Customize定制Purchase购买等。每个选项对象统一由以下字段组成label/extendedLabel/header按钮文案、扩展文案以及在选择站点对话框中的标题全部通过translate()实现 i18ngetUrl返回操作目标 URL 的函数如购买跳转到/checkoutactionRedux action creator触发对应状态变更如activate动作hideForTheme判定函数决定该选项在指定state / themeId / siteId / origin组合下是否隐藏——这是整个选项体系最核心的机制。核心操作清单getAllThemeOptions()返回的完整选项如下选项 key用途关键隐藏条件摘录purchase单独购买 Premium 主题Jetpack 非 Atomic 站点、未登录、无站点、非 Premium、已购买/已激活、捆绑软件集、第三方主题不可购买subscribe订阅第三方Marketplace主题暂存站点、Jetpack 非 Atomic、未登录、已订阅、捆绑软件集、非第三方主题、站点套餐不具备订阅资格upgradePlanJetpack 站点升级套餐以激活 Premium 主题非 Jetpack、Atomic 站点、未登录、无站点、非 Premium、已激活、已可用upgradePlanForBundledThemesWP.com 升级套餐激活捆绑软件集主题Jetpack 站点、Atomic、未登录、非捆绑软件集主题等upgradePlanForDotOrgThemesWP.com 升级套餐激活社区WP.org主题已具备FEATURE_INSTALL_THEMESWPCOM_FEATURES_COMMUNITY_THEMES、未登录、非 WP.org 主题等upgradePlanForExternallyManagedThemes升级套餐以订阅第三方主题非第三方主题、站点已具备订阅资格、已激活等activate激活主题未登录、多站点 Jetpack、捆绑软件集但无安装插件权限、已激活、非 WP.com 主题且非 Atomic、Premium 但未可用deleteTheme删除主题仅 Jetpack 站点非 Jetpack、origin 为wpcom、站点无此主题、已激活customize定制/编辑主题无edit_theme_options权限、主题未激活FSE 激活时文案变为 Edittryandcustomize尝试并定制旧方案Live Preview 已支持、shouldShowTryAndCustomize为假时隐藏livePreview预览并定制块主题 Live Preview不支持 Live Preview 时隐藏preview打开主题演示站点Demo site支持 Live Preview 或不存在演示 URL 时隐藏signup引导新用户注册并选择该主题已登录且有站点时隐藏文案根据shouldSelectSite在 Activate 与 Get started 之间切换info打开主题详情页始终可用separator菜单分隔线—动态显隐的原理hideForTheme每个选项的可见性依赖大量 Redux selector 的组合判定。以activate为例theme-options.jsconst activate { label: translate( Activate ), extendedLabel: translate( Activate this design ), header: translate( Activate on: ), action: activateAction, hideForTheme: ( state, themeId, siteId ) ! isUserLoggedIn( state ) || ! siteId || isJetpackSiteMultiSite( state, siteId ) || ( doesThemeBundleSoftwareSet( state, themeId ) ! siteHasFeature( state, siteId, WPCOM_FEATURES_INSTALL_PLUGINS ) ) || ( isExternallyManagedTheme( state, themeId ) ! getTheme( state, siteId, themeId ) ! isMarketplaceThemeSubscribed( state, themeId, siteId ) ) || isThemeActive( state, themeId, siteId ) || ( ! isWpcomTheme( state, themeId ) ! isSiteWpcomAtomic( state, siteId ) ) || ( isThemePremium( state, themeId ) ! isPremiumThemeAvailable( state, themeId, siteId ) ), };由此可以推断模块的交互设计原则选项是否展示完全由当前用户 当前站点 主题属性三者共同决定比如 Premium 主题在用户没有对应套餐时不展示激活而是展示购买或升级套餐从而把复杂的商业规则收敛在选项层而不是散落在各 UI 组件中。选项的接线connectOptionsHOC文件末尾导出connectOptions compose( localize, withIsFSEActive, connectOptionsHoc )theme-options.js其作用是把每个选项的getUrl绑定到当前state、把action绑定到dispatch、并按defaultOption / secondaryOption / getScreenshotOption属性挑选默认与次要操作。它还通过localizeThemesPath对 URL 做本地化前缀处理未登录且属于Magnificent语言环境时给/theme/...路径加 locale 前缀。WooCommerce 场景另有 getWooMyCustomThemeOptions为商店站点提供 Store Designer 快速编辑、Editor 高级定制、Store preview 等专属选项。主父组件与路由控制README 中提到的主父组件main.jsx在现仓库中已拆分为两层路由控制器 controller.jsx控制器负责解析路由参数并驱动数据预取关键函数包括getProps( context )从context.params提取category / tier / filter / vertical / view / site_id并从context.query.s取得搜索词同时计算analyticsPath / analyticsPageTitle见 helpers.js 的getAnalyticsData搜索词、tier、filter、站点参数都会拼进埋点路径loggedOut( context, next )未登录时渲染 LoggedOutComponentfetchThemeData( context, next )以siteIdwpcom预取主题列表命中 Redux 缓存则跳过并记录ssr.get_themes_fetch_cache.hit/miss指标fetchModernShowcaseData在themes/showcase-modern配置开启且未登录时为现代版 Showcase 的根页面并行预取FAVORITES_QUERY / FRESH_QUERY / PARTNER_QUERY三组推荐数据fetchThemeFilters调用wpcom.req.get( /theme-filters, { apiVersion: 1.2, locale } )拉取主题筛选词表并 dispatchTHEME_FILTERS_ADD若干 legacy 路由 301 重定向函数redirectSearchAndType等。展示容器 theme-showcase.jsxThemeShowcase是模块的主父组件922 行承担静态筛选 TabMy Themes / Recommended现代版显示为 Discover/ All三类静态 Tab 与主题学科subjectTab 的组装Woo Express 站点会裁剪 Tab见getTabFiltersTier 下拉getTiers()遍历THEME_TIERS定义于 client/components/theme-tier/constants只保留isFilterable的档位并始终在最前插入 All搜索逻辑doSearch用正则/([\w-]*):([\w-]*)/g从搜索框中解析filter:term语法将其映射为筛选字符串用连接并从搜索词中剔除未登录且无学科筛选时搜索会自动定位到 All 分类主题集合Collections通过 collections/collection-definitions 与ShowcaseThemeCollection渲染如 recommended 等集合视图Frequently Asked Questions内嵌 themes-faq/index.tsx可折叠 FAQ含 Premium 主题、付费主题、编辑主题等条目展开/收起均有 Tracks 埋点其他主题预览theme-preview.jsx、激活确认activation-modal.tsx、升级横幅banners-modern/plan-upgrade-banner、站点切换弹窗、错误提示等均由其组合。themes-selection.jsx搜索框 主题列表的组合组件README 将 themes-selection.jsx 描述为组合搜索框与下方主题列表的大组件。它在当前实现中由三层构成1. 查询构造buildThemesSelectionQueryexport function buildThemesSelectionQuery( { search , page 1, tier , filter , vertical , hiddenFilters [], tabFilter, sourceSiteId wpcom, premiumThemesEnabled true, } {} ) { const number ! [ wpcom, wporg ].includes( sourceSiteId ) ? 2000 : 100; return { search, page, tier: premiumThemesEnabled ? tier : free, filter: [ filter, vertical ].filter( Boolean ).concat( hiddenFilters ).join( , ), number, ...( tabFilter recommended { collection: recommended } ), ...( tabFilter all { sort: date } ), }; }要点每页数量numberWP.com / WP.org 源为 100Jetpack 等不支持分页的源为 2000注释明确说明这是为避免缓存 key 漂移而导出的精确查询形状tier在premiumThemesEnabled为假时强制为free站点未启用 Premium 主题时降级为免费档tabFilter recommended时追加collection: recommendedall时按日期排序组件在componentDidMount时若当前查询无search / filter / tier会自动incrementPage()预取第二页形成滚动分页的缓冲带。2. 连接层ConnectedThemesSelectionconnect映射中完成两件重要的事WP.org 主题的按需混入当forceWpOrgSearch且有搜索词、且不在recommended / my-themesTab、且 tier 为空或为free且站点可安装主题时才发起wporg查询并把 WP.com 的 filter 关键词拼进 WP.org 的搜索词清除subject:前缀与 -字符Bookmark 滚动定位通过getThemesBookmark实现记住上次浏览位置在 ThemeShowcase 的componentDidMount中scrollIntoView。3. 分页状态容器ThemesSelectionWithPage页面page状态无法放入ThemesSelection自身connect中的 selector 需要完整查询对象因此用高阶容器管理page并在siteId / search / tier / filter / vertical / tabFilter任一变化时resetPage()。helpers.jsURL 构造、结果混合与埋点辅助helpers.js 提供多个被控制器与组件复用的工具函数主题展示 URL 构造器constructThemeShowcaseUrlexport function constructThemeShowcaseUrl( { category, vertical, tier, filter, siteSlug, search, locale, isLoggedIn, isCollectionView, } ) { const siteIdSection siteSlug ? /${ siteSlug } : ; const categorySection category category ! DEFAULT_STATIC_FILTER ? /${ category } : ; const verticalSection vertical ? /${ vertical } : ; const tierSection tier tier ! all ? /${ tier } : ; let filterSection filter ? /filter/${ filter } : ; filterSection filterSection.replace( /\s/g, ); const collectionSection isCollectionView ? /collection : ; let url /themes${ categorySection }${ verticalSection }${ tierSection }${ filterSection }${ collectionSection }${ siteIdSection }; url localizeThemesPath( url, locale, ! isLoggedIn ); return buildRelativeSearchUrl( url, search ); }URL 形态汇总片段规则分类/themes/{category}与默认静态筛选相同时省略垂直方向/themes/{category}/{vertical}价格档非all时追加/tier段筛选/filter/{value}空格替换为集合视图追加/collection站点末尾追加/{siteSlug}搜索词由buildRelativeSearchUrl转为?s...查询参数WP.com 与 WP.org 主题的插序算法interlaceThemes该函数实现搜索结果混合排序规则在代码注释中写得非常明确helpers.js仅在有搜索词时才纳入 WP.org 主题若搜索词与某个主题的name或id精确匹配不区分大小写该主题排第一WP.com 主题整体优先于 WP.org 主题排除已退役retired的 WP.org 主题以及同时在 WP.com 也存在的重复主题通过wpComThemesSlugs.includes( theme.id.toLowerCase() )判断只有在 WP.com 列表已到最后一页isLastPage时才把 WP.org 主题追加到尾部带搜索词时WP.com 侧同样过滤掉退役主题端点返回退役主题是已知行为见代码引用的 PR #78231 注释。export function interlaceThemes( wpComThemes, wpOrgThemes, searchTerm, isLastPage ) { const isMatchingTheme ( theme ) { if ( ! searchTerm || theme.retired ) return false; return ( theme.name?.toLowerCase?.() searchTerm?.toLowerCase() || theme.id?.toLowerCase?.() searchTerm?.toLowerCase() ); }; const includeWpOrgThemes !! searchTerm; const wpComThemesSlugs wpComThemes.map( ( theme ) theme.id ); const validWpOrgThemes includeWpOrgThemes ? wpOrgThemes.filter( ( theme ) ! wpComThemesSlugs.includes( theme?.id?.toLowerCase() ) ! RETIRED_THEME_SLUGS_SET.has( theme?.id?.toLowerCase() ) ) : []; // ... 精确匹配置顶 → WP.com 主题 → 最后一页时WP.org 主题 }其他工具trackClick / addTracking为选项 action 追加 Google AnalyticsgaRecordEvent( Themes, ... )与 Tracks 埋点包装getTierRouteParam()由THEME_TIERS的 key 生成可选路由参数正则:tier(free|premium|...)?shouldSelectSite登录且未选定站点且拥有多个站点时操作需先弹站点选择器localizeThemesPath未登录 Magnificent locale 时给/theme路径加 locale 前缀、给/start/with-theme路径调addLocaleToPath。激活后的 Thanks 对话框thanks-modal.jsx的演进README 提到的thanks-modal.jsx激活后感谢对话框在现仓库中已演化为 TSX 实现的 activation-modal.tsx。它提供Basic setup / Full setup 二选一预览basic_setup用theme: stylesheet、hide_bannerstrue、可选style_variation取变体的title而非 slug与 theme-preview.jsx 约定一致和languagelocale参数在用户现有站点域名上预览full_setup则加载官方 demo 站点demotrueiframetruetheme_previewtrue对应 theme-headstart 端点会复制的效果Tracks 埋点挂载后触发calypso_theme_activation_modal_view携带theme / source / is_site_launched / site_age_in_daysActivation 动作通过activateThemeaction 完成激活并管理isActivating状态。主题预览与搜索组件theme-preview.jsx基于WebPreview组件实现主题详情页中的实时预览预览 URL 形如demoUrl?demotrueiframetruetheme_previewtruelanguagelocale非en时追加语言参数并通过appendStyleVariationOptionToUrl把 style variation 的title写入style_variation查询参数。激活完成后isActivating由真转假会自动关闭预览。搜索栏theme-search-card→SearchThemesREADME 中的theme-search-card对应通用组件 client/components/search-themes/index.tsx。它接收query、onSearch与recordTracksEvent在清空或提交搜索框时回调onSearch并记录 Tracks 事件配套的 search-themes-tracks.js 负责统计搜索词与 WP.com / WP.org 结果混合后的展示数据。Showcase 侧把doSearch的输出交给该组件形成输入 → URL 更新 →themes-selection重新查询的闭环。路由与多视图的最终组装多站点、单站点与 Jetpack 视图的实际分流由路由注册完成未登录loggedOut控制器渲染 [logged-out 组件]现代版 Showcase 需要themes/showcase-modern配置开关单站点 WP.comsingle-site-wpcom.jsx单站点 Jetpacksingle-site-jetpack.jsx多站点走 controller-logged-in.jsx 中基于getSiteId的调度逻辑配合shouldSelectSite弹窗选择站点。此外 validate-filters.js 负责校验 URL 中的 filter 是否合法is-full-site-editing-theme.ts 判断主题是否为 FSE全站编辑主题——该结果会直接影响theme-options.js中customize选项的文案FSE 下为 Edit与 Live Preview 的可用性。小结client/my-sites/themes/是 wp-calypso 中一个路由 容器 选项定义 数据查询分层清晰的业务模块theme-options.js用统一的label / getUrl / action / hideForTheme模型把激活、定制、购买、订阅、升级等全部主题操作收敛为可组合、可动态显隐的选项集合themes-selection.jsx与helpers.js负责查询构造、分页管理以及 WP.com/WP.org 结果的混合排序theme-showcase.jsx与控制器完成路由解析、SSR 预取和 UI 组装。理解这些核心文件的协作关系后无论是排查主题操作显示异常、新增主题操作类型还是调整搜索结果的排序规则都能在源码层面快速定位到对应位置。参考文件索引模块文档client/my-sites/themes/README.md操作定义theme-options.js辅助函数helpers.js组合组件themes-selection.jsx主容器theme-showcase.jsx路由控制器controller.jsx、controller-logged-in.jsx激活对话框activation-modal.tsx主题预览theme-preview.jsx搜索组件client/components/search-themes/index.tsx价格档常量client/components/theme-tier/constants主题状态逻辑client/state/themes含STATIC_FILTERS、DEFAULT_STATIC_FILTER、RETIRED_THEME_SLUGS_SET等赞分享前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载相关推荐wp-calypso Domains 模块深度解析My Sites 域管理路由架构与实现wp calypso Domains 模块深度解析My Sites 域管理路由架构与实现 导读 本文以 client/my sites/domains/REA前端CMSwp-calypso Plugins 模块架构解析路由、控制器与插件管理视图wp calypso Plugins 模块架构解析路由、控制器与插件管理视图 本文以 wp calypso 仓库中 client/my sites/plugi前端CMSWordPress.com 站点设置模块架构解析从 FormBase 混入到按站点类型分页的 Calypso 实现WordPress.com 站点设置模块架构解析从 FormBase 混入到按站点类型分页的 Calypso 实现 本站点设置Site Settings模前端CMS上一篇oauth2-proxy 接入 Facebook 登录Provider 配置指南与源码原理解析下一篇Logto 登录体验短语包 logto/phrases-experience从版本演进看其 i18n 体系与认证安全能力建设创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表