ARTICLE DETAIL

资讯详情

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

wp-calypso My Sites 模块开发指南:路由、控制器与 section 目录组织规范

wp-calypso My Sites 模块开发指南:路由、控制器与 section 目录组织规范 前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载本指南以 client/my-sites/README.md 为骨架系统讲解 WordPress.com Calypso 前端wp-calypso中My Sites站点管理区域的路由与视图组织方式。你将掌握 section 模块的标准目录结构index.jscontroller.jsmain.jsxREADME.md、控制器挂载顶层组件与处理数据逻辑的职责划分、#primary/#secondary渲染区域的约定以及共享组件的放置策略并结合仓库内真实源码如 activity、backup、domains 等子模块理解这套规范的实际落地形态。一、My Sites 区域是什么在 wp-calypso 中My Sites是登录用户进入站点管理后的核心区域统计stats、页面pages、文章posts、媒体media、评论comments、主题themes、插件plugins、域名domains、购买purchases、营销marketing、备份backup等站点级功能全部汇聚于此。该区域由 client/my-sites 目录承载它同时承担两类职责视图与路由逻辑_My Sites区域的页面路由route定义与请求处理器handler集中在此子目录结构约定所有站点管理相关的 sub-section 与组件都放在该目录下形成清晰的归属感sense of place。README 明确了一条目录纪律目录根部只应存在index.js和controller.js两个入口文件外加每个模块目录都有的README.md。从当前仓库看根目录确实只有controller.jsx路由处理器随项目演进从controller.js迁移为 JSX 文件与各子目录而不同子 section 各自拥有独立的 controller 文件与main.jsx组件来初始化自己的渲染树。这种组织方式的价值在于模块被封装在合理的分组之下开发者一眼就能判断这个东西属于哪里同时任意 UI 组件都可以被复用——例如my-sites/site组件就在很多地方被引用不必重复造轮子。二、新增一个 section 的标准结构README 给出了新建 section 模块的典型目录形态/section ├── index.js ├── controller.js ├── main.jsx ├── README.md ├── ... // components relevant to the section对照当前仓库例如 client/my-sites/activity 就完全符合该模式activity/ ├── index.js # 路由注册 ├── controller.jsx # 路由处理器controller ├── activity-log/ # section 内部组件 ├── activity-log-v2/ ├── filterbar/ ├── activity-log-banner/ └── ...需要注意的演进细节README 写作时期望controller.js是纯 JS 文件而当前仓库中多数子模块如 activity/controller.jsx、根目录 controller.jsx已实际采用.jsx扩展名——因为控制器需要渲染 JSX 顶层组件。新增模块时按 README 的三件套 README组织扩展名可跟随项目现状选择.js或.jsx。2.1 index.js路由的唯一出口所有主路由primary routes必须在index.js中声明。以 activity/index.js 为最小示例import page from automattic/calypso-router; import { makeLayout, render as clientRender } from calypso/controller; import wrapInSiteOffsetProvider from calypso/lib/wrap-in-site-offset; import { navigation, siteSelection, sites } from calypso/my-sites/controller; import { activity, showNotAuthorizedForNonAdmins } from ./controller; export default function () { page( /activity-log, siteSelection, sites, makeLayout, clientRender ); page( /activity-log/:site, siteSelection, navigation, activity, showNotAuthorizedForNonAdmins, wrapInSiteOffsetProvider, makeLayout, clientRender ); }这里可以提炼出 My Sites 路由链的通用中间件栈范式siteSelection站点选择中间件。若 URL 中未携带站点片段会进入站点选择流程Jetpack Cloud 环境下则委托给cloudSiteSelection见 controller.jsxsites无站点片段时的站点列表渲染/跳转逻辑并处理?verified1等查询参数的通知见同文件 L868navigation在#secondary区域渲染 My Sites 左侧导航见 L855section 自己的 handler如activity、showNotAuthorizedForNonAdminsmakeLayoutclientRender组装整体布局并完成客户端渲染。index.js导出的default function由 Calypso 的 section 注册机制client/sections.js等按需加载调用因此每个子模块可以独立拆分 bundle。2.2 controller挂载顶层组件、处理数据、修改状态README 对控制器的职责定义是挂载mount任何顶层组件、处理任何核心数据逻辑、以及/或者修改组件状态。以 activity/controller.jsx 为例其activityhandler 完整演示了这套职责export function activity( context, next ) { const state context.store.getState(); const siteId getSelectedSiteId( state ); const filter siteId getActivityLogFilter( state, siteId ); const queryFilter queryToFilterState( context.query ); if ( ! isEqual( filter, queryFilter ) ) { context.store.dispatch( setFilter( siteId, queryFilter, true ) ); } recordTrack( calypso_activitylog_view, queryFilterToStats( queryFilter ) ); context.primary config.isEnabled( activity-log/v2 ) ? ( ActivityLogV2 / ) : ( ActivityLog siteId{ siteId } context{ context } / ); next(); }三个关键动作一一对应 README 的职责描述处理核心数据逻辑从context.store.getState()读取当前选中站点并用queryToFilterState把 URL 查询参数context.query解析为活动日志过滤器状态修改状态当 store 中的过滤器与 URL 查询参数不一致时dispatch( setFilter( ... ) )同步 Redux 状态使刷新/分享链接后 UI 与 URL 保持一致挂载顶层组件将渲染树写入context.primary见下方渲染区域约定并按config.isEnabled( activity-log/v2 )功能开关在 V1/V2 两套活动日志实现间切换。控制器遵循中间件约定处理完自身逻辑后必须调用next()放行后续中间件如权限校验、makeLayout。此外controller 也常用来做权限包装。同一文件中的showNotAuthorizedForNonAdmins用IsCurrentUserAdminSwitch把context.primary包起来非管理员看到NotAuthorizedPage管理员看到真实内容——权限校验也被视为控制器职责的一部分。2.3 main.jsx#primary区域的第一个渲染组件README 有一条硬性约定任何 section 在#primary区域渲染的第一个组件应当命名为section/main.jsx且该组件应使用components/main作为其 wrapper。也就是说main.jsx是 section 渲染树的根组件而 components/main/index.tsx 提供了统一的页面外壳export default function Main( { className , id , children, wideLayout false, fullWidthLayout false, isLoggedOut false, ariaLabel, }: MainProps ) { const classes clsx( className, main, { is-wide-layout: wideLayout, is-full-width-layout: fullWidthLayout, is-logged-out: isLoggedOut, } ); return ( main className{ classes } id{ id || undefined } rolemain aria-label{ ariaLabel } { children } /main ); }Main组件值得注意的能力对照其 props 接口wideLayout切换is-wide-layout样式类让内容区占满更宽布局统计等数据密集型页面常用fullWidthLayout切换is-full-width-layout用于需要通栏展示的场景isLoggedOut登出态页面样式ariaLabel/rolemain保证语义化与无障碍访问。当前仓库中 backup/main.jsx、marketing/main.jsx、plugins/main.jsx 等均遵循main.jsxcomponents/main外壳的约定。2.4 README.md每个模块自文档化每个模块目录都应自带一份简短、自解释的README.md说明该 section 的用途与关键约定。这也是 Calypso 全仓库的通用习惯client/下几乎所有模块目录都有 README便于后来者快速定位与接手。三、渲染区域约定#primary 与 #secondaryREADME 提到#primary的同时隐含了 Calypso 布局系统的两栏约定可从根控制器与布局实现进一步确认#primary内容主区section 的main.jsx渲染树最终落在这里#secondary侧栏区navigation中间件把 My Sites 的左侧导航渲染到这里见 controller.jsx L855-L858 的context.secondary createNavigation( context )。控制器通过向context.primary/context.secondary赋值把渲染树交给makeLayout统一组装最终由clientRender输出到页面。这也是为什么 README 要求#primary的第一个组件必须是main.jsx——它保证了每个 section 都有统一的外壳入口页面结构可预测、可测试。四、共享组件放哪里README 给出了放置原则如果一个可复用的独立组件与 My Sites 区域直接相关那么放在client/my-sites根目录下是合适的——当然它需要一份自己的 README.md 来保持自文档化。从当前仓库根目录列表client/my-sites看这类共享层确实直接挂在根下例如controller.jsx提供siteSelection、navigation、sites等跨 section 复用的路由中间件navigation左侧站点导航组件sites站点选择/列表组件sidebar、site-indicator、current-site、no-results 等通用 UIdifm-route-utils.js与替你完成Do It For Me流程相关的路由工具函数。与之相对只被某个 section 内部使用的组件应留在该 section 自己的子目录中如activity/activity-log/、domains/内部的组件树而不是上提到根目录——这正是模块封装 清晰归属感的具体体现。五、对照仓库规范在真实模块中的落地把 README 的规范映射到仓库内的真实模块可以快速验证其普适性Sectionindex.js路由controller处理器main.jsx顶层组件活动日志activity/index.jsactivity/controller.jsx经 controller 挂载ActivityLog/ActivityLogV2备份backup/index.jsbackup 子目录内 controllerbackup/main.jsx营销marketing/index.jsmarketing 子目录内 controllermarketing/main.jsx插件plugins/index.jsplugins 子目录内 controllerplugins/main.jsx主题/商店theme、woocommerce各自目录内 controllertheme/main.jsx、woocommerce/main.jsx可以从源码结构推断出的通用规律是find_files显示仓库中共有 30 个client/my-sites/*/index.js路由注册文件activity、backup、checkout、comments、customer-home、customize、domains、exporter、google-my-business、importer、invites、jetpack-search、marketing、marketplace、media、migrate、pages、people、plans、posts 等而main.jsx并非每个 section 都显式存在——部分 section 的顶层渲染组件仍以main.jsx命名另一些则直接在 controller 中挂载命名组件。这说明index.jscontroller.js(x)是刚性约定main.jsx是推荐形态当 section 的顶层组件需要被多个路由复用或需要按功能开关切换实现时开发者会灵活选择直接在 controller 中挂载具名组件。六、实践清单按规范新增一个 My Sites section结合 README 与仓库实现新增 section 的推荐步骤在 client/my-sites 下创建/section/目录编写index.js用page()注册所有主路由并组装中间件链siteSelection → (navigation) → 你的 handler → makeLayout → clientRender编写controller.js(x)实现各路由 handler读取context.store/context.query必要时dispatch更新 Redux 状态最终把渲染树赋给context.primary侧栏导航赋给context.secondary并在末尾调用next()编写main.jsx或在 controller 中直接挂载的具名顶层组件使用components/main作为 wrapper按需开启wideLayout/fullWidthLayout为模块补一份自解释的README.md若产生可跨 section 复用的组件将其上提到client/my-sites根目录并单独撰写 README。这套目录即架构的约定让 wp-calypso 在拥有数百个页面、数千个组件的情况下依然保持路由、控制器与渲染树三者之间的清晰映射关系——理解它是上手 Calypso 站点管理开发的第一步。赞分享前端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前端CMSwp-calypso Reader 模块指南路由体系、数据流与 Block 渲染开发详解wp calypso Reader 模块指南路由体系、数据流与 Block 渲染开发详解 Reader阅读器是 wp calypso 中承载 WordPr前端CMS创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表