ARTICLE DETAIL

资讯详情

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

Calypso Modular Signup Framework 完全指南:从零搭建自定义注册流程与步骤

Calypso Modular Signup Framework 完全指南:从零搭建自定义注册流程与步骤 前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载导读Modular Signup模块化注册是 Calypso 面向注册场景的核心框架它把「将未登录、没有账号的用户转化为已登录用户」这一目标拆解为Flow流程与Step步骤两层抽象一个 Flow 由一组按特定顺序组织的 Step 组成每个 Step 是一个负责收集数据的 React 组件。本文以 client/signup/README.md 为骨架结合client/signup/config/与client/lib/signup/的真实源码完整讲解如何注册一个新 Flow、定义一个新 Step、实现步骤组件并通过SignupActions驱动流程前进最后以官方 Hello World 教程串起全流程。读完本文你将能够在 Calypso 中独立新增一条类似wordpress.com/start/your-flow的注册流程并理解其背后的依赖存储Dependency Store与进度存储Progress Store机制。框架核心概念Flow 与 StepModular Signup 的定位在文档中表述得非常清楚它是 Calypso 中用于创建「把没有账号的未登录用户变成已登录用户」的流程的框架。整个框架只围绕两个抽象展开Flow流程一组按特定顺序组织的步骤集合。例如account流程只有一步创建账号free流程则包含创建账号与选择域名两步。Step步骤一个 React 组件负责为流程收集数据。例如用户填写邮箱密码的user步骤、选择域名的domains步骤、选择套餐的plans步骤。在仓库中这两个概念分别由 client/signup/config/flows-pure.js 与 client/signup/config/steps-pure.js 定义。它们都遵循「纯函数 依赖注入」的模式generateFlows( dependencies )与generateSteps( dependencies )接受一组可覆写的回调如getSignupDestination、createAccount、addPlanToCart默认值为noop便于测试与复用。从 flows-pure.js 可以看到generateFlows接收的依赖注入项包括getRedirectDestination账号创建后重定向目标getSignupDestination通用注册完成后目标getLaunchDestination、getDomainSignupFlowDestination、getEmailSignupFlowDestination、getWithThemeDestination、getWithPluginDestination、getDIFMSignupDestination等各类细分场景的目标函数。文件末尾通过Object.fromEntries( flows.map( ( flow ) [ flow.name, flow ] ) )将数组转换为以name为键的对象并默认导出flows-pure.jssteps-pure.js的generateSteps则直接返回一个以stepName为键的对象。创建新的 Flow根据原文档新增一个 Flow 的方式是编辑flows-pure.js在generateFlows函数的flows数组中追加一个属性对象。Flow 的必需属性steps数组按向用户展示的顺序列出该流程包含的所有步骤。可用的步骤清单见 client/signup/config/steps-pure.js。destinationstring或function决定用户完成流程最后一步后重定向到哪个页面。若为函数则会被调用参数为注册流程中累积的所有依赖dependencies返回值作为重定向目标。Flow 的可选属性属性类型说明descriptionstring对该流程用途的简要描述lastModifiedstring流程最近更新的日期戳disallowResumeboolean为true时用户刷新页面会回到第一步不保留进度原文档给出的最小示例const account { steps: [ user-social ], destination: / };在真实仓库中account流程的定义更为完整flows-pure.js{ name: account, steps: [ userSocialStep ], destination: getRedirectDestination, description: Create an account without a blog., lastModified: 2025-02-18, get pageTitle() { return translate( Create an account ); }, showRecaptcha: true, providesDependenciesInQuery: [ toStepper ], optionalDependenciesInQuery: [ toStepper ], hideProgressIndicator: true, },注意steps数组中实际使用userSocialStep变量isEnabled( signup/social-first ) ? user-social : user见 flows-pure.js这是仓库中为 social-first 注册模式预留的取舍逻辑。文档还特别强调一条硬性约束Flow 必须至少包含一个能创建用户并提供 bearer token 的步骤这对应步骤定义中的providesToken属性详见下文「创建新的 Step」。浏览真实流程可以看到这条约束的体现几乎每个面向新用户注册的流程free、with-theme、with-plugin、onboarding、ecommerce、reader等都把user或user-social放在步骤列表开头。已注册的 Flow 示例仓库现状flows-pure.js中定义了数十个流程这里摘录几个有代表性的数据截至当前仓库hosting[ userSocialStep, hosting-decider ]创建账号并跳转到托管站点流程分支步骤flows-pure.jsfree[ userSocialStep, domains ]创建账号和博客并默认免费套餐flows-pure.jswith-theme[ userSocialStep, domains-theme-preselected, plans-theme-preselected ]从外部来源预选主题flows-pure.jsonboarding-registrationless[ domains, plans-new, user-new ]无账号无站点的直接结算流程flows-pure.jsplans-first[ plans, domains, userSocialStep ]先选套餐再注册的流程flows-pure.js。这些真实定义展示了文档未展开的扩展属性showRecaptcha、providesDependenciesInQuery、optionalDependenciesInQuery控制从 URL query 注入依赖、hideProgressIndicator、persistsDomainsOnReEntry、enableBranchSteps、forceLogin等说明 Flow 配置是一个高度可定制的声明式结构。Flow 的路由可用性一旦在flows-pure.js中添加了 Flow它就会自动在/start/flow-name地址可用其中flow-name是flows对象中该 Flow 的键即name属性。例如添加名为hello的流程后访问/start/hello即可进入。创建新的 Step任何人都可以为 Flow 设计师创建可复用的 Step。新 Step 定义在 client/signup/config/steps-pure.js 中由若干属性组成。Step 的属性stepName必需步骤的标识符供flows-pure.js引用。dependencies可选数组声明本步骤处理时需要从其他步骤获取哪些依赖。providesDependencies可选数组向框架声明本步骤预期会提供哪些依赖。如果实际提供的依赖与声明不符缺少或多余框架会抛出错误除非使用了optionalDependencies。optionalDependencies可选数组列出providesDependencies中哪些是可选的这些值在步骤提交时缺失不会报错。delayApiRequestUntilComplete可选boolean为true时步骤的apiRequestFunction要等到用户提交完流程中的所有步骤后才被调用。适用于用户可能在注册过程中反复回退修改的步骤。props可选对象存放特定于某步骤的自定义属性。仓库中domains步骤是这些属性的综合范例steps-pure.jsdomains: { stepName: domains, apiRequestFunction: createSiteWithCart, providesDependencies: [ siteId, siteSlug, domainItem, themeItem, shouldHideFreePlan, isManageSiteFlow, signupDomainOrigin, siteUrl, lastDomainSearched, useThemeHeadstart, domainCart, ], optionalDependencies: [ shouldHideFreePlan, isManageSiteFlow, signupDomainOrigin, siteUrl, lastDomainSearched, useThemeHeadstart, ], props: { isDomainOnly: false }, delayApiRequestUntilComplete: true, },user步骤则展示了providesToken与依赖声明steps-pure.jsuser: { stepName: user, apiRequestFunction: createAccount, providesToken: true, providesDependencies: [ bearer_token, username, marketing_price_group, redirect, allowUnauthenticated, is_new_account, oauth2_client_id, oauth2_redirect, ], optionalDependencies: [ redirect, allowUnauthenticated, is_new_account, oauth2_client_id, oauth2_redirect, ], props: { isSocialSignupEnabled: config.isEnabled( signup/social ) }, },其中providesToken: true正是文档强调的「至少一个能创建用户并提供 bearer token 的步骤」的判定依据——bearer_token在providesDependencies中声明由createAccount的 API 响应带回。注册步骤的 React 组件Step 的定义不止于数据声明还需要在 client/signup/config/step-components.js 中把stepName映射到实现该步骤的 React 组件模块并以内部依赖的方式 require 该组件。仓库的实现是一个stepNameToModuleName映射对象加一个异步加载函数step-components.jsconst stepNameToModuleName { clone-start: clone-start, domains: domains, domain-only: domains, hosting-decider: hosting-decider, plans: plans, user: user, user-social: user, // ... }; export async function getStepComponent( stepName ) { const moduleName stepNameToModuleName[ stepName ]; if ( ! moduleName ) { console.error( Error: unknown stepName to retrieve the component for. ); return; } const module await import( /* webpackChunkName: async-load-signup-steps-[request] */ /* webpackInclude: /signup\/steps\/[0-9a-z/-]\/index\.[j|t]sx$/ */ calypso/signup/steps/${ moduleName } ); return module.default; }可以看到多个stepName可以复用同一个组件目录如user、user-social、user-new、oauth2-user都指向user并且组件通过webpackInclude限定为signup/steps/下的index.jsx/index.tsx配合webpackChunkName实现按步骤分包的异步加载。实现一个 Step 组件Step 的 React 组件实现位于/signup/steps/下的独立目录中。组件必须使用SignupActions模块以内部依赖方式引入import SignupActions from calypso/lib/signup/actions;SignupActions让 Modular Framework 接管步骤收集到的数据。因此步骤组件必须包含一个让用户进入流程下一步的 UI 元素且处理该元素的函数必须使用SignupActions的submitSignupStep方法。此外还应调用this.props.goToNextStep()让框架渲染流程的下一步通常还需要调用event.preventDefault()以跳过表单的原生提交处理。文档中的完整示例function handleSubmit( event ) { event.preventDefault(); SignupActions.submitSignupStep( { stepName: this.props.stepName, } ); this.props.goToNextStep(); }submitSignupStep的参数如下step对象必填属性stepName为正在提交的步骤名providedDependencies可选对象描述该步骤向 Dependency Store 添加的数据。仅用于不来自 API 请求的数据——来自apiRequestFunction回调的依赖会自动进入依赖存储无需在此重复声明wasSkipped可选标志位为true表示某个可选步骤被跳过。背后的状态模型Progress Store 与 Dependency Store文档指出提交的步骤保存在Progress Store中等待其依赖被满足例如创建站点的步骤必须等待用户账号创建完成。一旦依赖满足步骤被处理其结果保存进Dependency Store供其他步骤使用。client/lib/signup/README.md 补充了这两者的细节SignupProgressStore通过SUBMIT_SIGNUP_STEPaction 收集用户提交的步骤列表。步骤进入存储后会带一个status字符串属性取值包括in-progress、processing、pending、completed、invalid。通过SignupProgressStore#get()获取步骤数组。SignupActions核心 action 有两个——submitSignupStep( step, providedDependencies )用户提交步骤与completeSignupStep( step, errors, providedDependencies )步骤被 API 处理。step对象中的apiRequestFunction可选决定了步骤的status是pending还是completed。若errors非空错误会附加到步骤上并将状态置为invalid若传了providedDependencies其信息会写入依赖存储。SignupDependencyStore凡是通过 action 提供了providedDependencies的步骤其信息都会进入此存储。README 中的示例展示了跨模块的读写import SignupActions from calypso/lib/signup/actions; import SignupDependencyStore from calypso/lib/signup/dependency-store; SignupActions.completeSignupStep( { stepName: example }, [], { userId: 1337 } ); SignupDependencyStore.get(); // { userId: 1337 }SignupFlowController初始化一个注册流程负责为带apiRequestFunction的步骤发起 API 请求并提供「获取当前步骤组件」与「流程完成回调」的能力。典型用法client/lib/signup/README.mdimport SignupFlowController from calypso/lib/signup/flow-controller; class SignupComponent extends React.Component { constructor() { super(); this.signupFlowController new SignupFlowController( { flowName: default, onComplete: function () { console.log( The user completed the flow. Redirect or log them in here. ); }, } ); } render() { const CurrentStepComponent this.signupFlowController.currentStep().component; return CurrentStepComponent /; } }apiRequestFunction把步骤提交给后端 API如果步骤需要先拿到其他步骤提供的数据才能向 API 提交可以为其在steps-pure.js中配置apiRequestFunction。该函数在步骤所需数据就绪时被调用。文档示例const object { stepName: user-social, dependencies: [ siteSlug ], apiRequestFunction: function ( callback, dependencies ) { wpcom.req.post( /some-endpoint, dependencies.siteSlug, function ( errors, response ) { callback( errors, { userId: response.userId } ); } ); }, };解读如下apiRequestFunction接收两个参数callback与dependencies此例中它调用某个 API 端点并期望返回userId请求成功时response.userId通过callback( errors, { userId } )写入 Dependency Store——这正是 API 请求产出的依赖无需写进providedDependencies的原因dependencies参数中包含步骤dependencies属性声明的所有依赖本例为siteSlug在函数被调用时传入。文档同时给出工程实践建议不要把apiRequestFunction写成内联匿名函数而应把实现放在StepActions即signup/config/step-actions.js当前仓库中为 client/lib/signup/step-actions/index.js中然后在步骤定义里引用const step { apiRequestFunction: stepActions.createSiteWithCart, };仓库中大量步骤遵循了这一模式。例如createAccountclient/lib/signup/step-actions/index.js内部处理了多种分支对onboarding-registrationless流程且在购买商品时直接跳过建号并返回allowUnauthenticated: true对 social 注册区分created_account成功响应中提取bearer_token、username、user_id等并组装registrationUserData。createSiteWithCart、addPlanToCart、addDomainToCart等也都在该文件中实现与steps-pure.js中apiRequestFunction: createSiteWithCart、apiRequestFunction: addPlanToCart的引用一一对应。Hello World 实战从零新增 Flow 与 Step文档提供了完整的 9 步实战教程以下按原步骤复现并补充细节。第 1 步创建步骤目录在/client/signup/steps下新建目录hello-world。第 2 步添加组件文件在hello-world目录下创建index.jsx。仓库中组件的命名规范是index.jsx或index.tsx与step-components.js中webpackInclude的正则约束一致。第 3 步编写 React 组件export default function HelloWorld() { return spanHello world/span; }第 4 步在step-components.js注册模块映射在stepNameToModuleName对象中加入映射const stepNameToModuleName { hello-world: hello-world-module-name, // Referencing signup/steps/hello-world-module-name/index.js };第 5 步在steps-pure.js中注册步骤在generateSteps返回的对象中加入步骤定义stepName必须与属性名一致const steps { hello-world: { stepName: hello-world, // has to match the property name }, };第 6 步在 flows 配置中注册流程在 flow 配置中加入新流程文档此处给出的文件名flow.js即流程定义文件当前仓库中对应 client/signup/config/flows-pure.jsconst flow { hello: { // This will be the slug for the flow, i.e.: wordpress.com/start/hello steps: [ hello-world, user ], // These are the steps that the user will be shown destination: /, // This is where the user will be taken once the flow is complete }, };说明hello是流程 slug访问地址为/start/hello步骤数组中同时包含hello-world自建步骤与user账号步骤恰好满足「流程必须包含能创建用户并提供 bearer token 的步骤」的约束。第 7 步本地验证第一步在隐身窗口打开https://calypso.localhost:3000/start/hello会被重定向到流程第一步/start/hello/hello-world页面应渲染出自定义的 React 组件。第 8 步让用户能前进到下一步在步骤组件的render方法中增加表单与按钮function render() { return ( form onSubmit{ this.handleSubmit } pThis is the step named { this.props.stepName }/p button classNamebutton typesubmit Get started /button /form ); }引入SignupActionsimport SignupActions from calypso/lib/signup/actions;并实现表单提交处理函数handleSubmit ( event ) { event.preventDefault(); SignupActions.submitSignupStep( { stepName: this.props.stepName, } ); this.props.goToNextStep(); };第 9 步端到端验证再次在隐身窗口打开https://calypso.localhost:3000/start/hello应重定向到第一步并渲染更新后的组件点击 Get started 按钮后应进入下一步。机制小结一次提交在框架中的完整旅程综合文档与源码一次「用户点击提交」在 Modular Signup 中的调用链可以归纳为步骤组件的事件处理器调用SignupActions.submitSignupStep( { stepName } )必要时携带providedDependencies与wasSkippedSignupProgressStore记录该步骤并标记状态in-progress/pending/completed等取决于是否有apiRequestFunction组件再调用this.props.goToNextStep()由框架推进到流程的下一步若步骤声明了dependencies框架等待这些依赖在 Dependency Store 中就绪后才触发apiRequestFunctionapiRequestFunction通过callback( errors, providedDependencies )把 API 结果写回 Dependency Store如bearer_token、siteId、siteSlug、cartItems供后续步骤消费全部步骤完成后框架调用 Flow 的destination字符串或依赖函数决定用户重定向去向。每一步的声明steps-pure.js、组件映射step-components.js、API 动作实现client/lib/signup/step-actions/index.js三者解耦这正是 Modular Signup 让不同业务团队能独立贡献步骤、自由组合流程的架构基础。赞分享前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载相关推荐终极Sysmon-Modular完整指南从零开始构建自定义Windows监控配置终极Sysmon Modular完整指南从零开始构建自定义Windows监控配置 Sysmon Modular是一个模块化的Microsoft Sysinte网络安全wp-calypso 注册流程状态管理指南Signup 模块的 Redux 组织与依赖存储实现wp calypso 注册流程状态管理指南Signup 模块的 Redux 组织与依赖存储实现 导读 本文基于 wp calypso 仓库中的 client/前端CMShystrix-cj扩展开发指南从零实现自定义限流规则Processor注册完全教程hystrix cj扩展开发指南从零实现自定义限流规则Processor注册完全教程 hystrix cj 是仓颉语言的熔断降级库内置了线程数、TPS、平测试开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表