
前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载引言在 WordPress.com 的 Calypso 界面中无论是套餐购买页、Jetpack 产品商店还是订阅续费入口几乎每一个涉及钱的地方都需要一个统一的组件来渲染计划Plan的价格。PlanPrice正是这样一个开箱即用的 React 组件它既能直接展示后端返回的预格式化价格字符串productDisplayPrice也能接收原始数字rawPrice自动完成货币符号、千分位、小数位等本地化格式化还能通过original/discounted两个属性优雅地呈现划线原价 折扣现价的促销组合。本文基于 wp-calypso 仓库 packages/components/src/plan-price/README.md 为核心骨架结合组件源码、样式表、单元测试与真实业务使用场景完整讲解该组件的全部 Props、渲染优先级、底层货币格式化原理及实战用法帮助你在自己的页面中快速接入规范化的价格展示。PlanPrice 是什么PlanPrice 是一个用于展示计划价格的通用 React 组件定义于 packages/components/src/plan-price/index.tsx通过automattic/components包对外导出。它的核心定位是展示一个计划的价格可带货币符号如$、€、kr.支持折扣场景当需要强调价格已打折时官方推荐的做法是用两个PlanPrice并排放入一个 flexbox 容器中一个打上original原价显示删除线另一个打上discounted折扣价绿色高亮支持价格区间传入一个二元数组rawPrice即可渲染出$99.99-139.99这样的区间价格可以用于任何需要展示计划价格的页面。它位于automattic/components组件库中因此任何依赖该包的 Calypso 应用包括client下的各个 section都可以直接复用。快速上手从 README 中的两个经典用法说起官方 README 给出了两种最典型的数据来源与用法。用法一直接使用后端返回的productDisplayPriceproductDisplayPrice是后端/purchases、/plans等 REST 端点返回的已经格式化好的价格字符串可能还包含 HTML 标记它通常会被存入 Redux 状态。此时组件会原样输出该字符串不做任何货币格式化function MyComponent( { purchaseId } ) { const purchase useSelector( ( state ) getRawByPurchaseId( state, purchaseId ) ); return PlanPrice productDisplayPrice{ purchase?.product_display_price } /; }也可以同时传入税款信息与促销标记PlanPrice productDisplayPrice{ purchase.productDisplayPrice } taxText{ purchase.taxText } isOnSale{ !! purchase.saleAmount } /;用法二传入rawPrice原始数字交给组件自动格式化当你有的是纯数字例如从购买记录或续费价格函数中计算出来的数值时使用rawPrice并配合currencyCode组件会调用getCurrencyObject完成货币符号、千分位、小数位等本地化处理PlanPrice productDisplayPrice{ purchase.productDisplayPrice } rawPrice{ getRenewalPrice( purchase ) } currencyCode{ purchase.currencyCode } taxText{ purchase.taxText } isOnSale{ !! purchase.saleAmount } /;注意上面的写法中同时传入了productDisplayPrice与rawPrice而二者的优先级规则在渲染优先级一节会详细说明——关键在于只有当rawPrice是数组价格区间时它才会覆盖productDisplayPrice。价格区间rawPrice传数组README 明确指出如果向rawPrice传入一个包含两个数字的数组组件将展示一个价格区间PlanPrice rawPrice{ [ 132.2, 110.4 ] } original / PlanPrice rawPrice{ [ 99.99, 87 ] } discounted /这是 README 中给出的完整示例。它来自 packages/components/src/plan-price/docs/example.jsx 和 index.stories.jsx 中展示的所有场景包括场景代码示例标准价格PlanPrice rawPrice{ 99.8 } /价格区间PlanPrice rawPrice{ [ 99.99, 139.99 ] } /零价格PlanPrice rawPrice{ 0 } /折扣价原价现价flexbox 中PlanPrice rawPrice{ 8.25 } original /PlanPrice rawPrice{ 2 } discounted /折扣价格区间original用[ 8.25, 20.23 ]discounted用[ 2.25, 3 ]带税信息追加taxText10%简单视图追加isInSignupsignup 流程中的简化展示Props 全解析从源码接口看 14 个可用属性PlanPrice 的所有 Props 都定义在同文件的PlanPriceProps接口中packages/components/src/plan-price/index.tsx#L93-L203同时组件类在render()中给出了各属性的默认值。下表汇总了完整清单属性类型默认值作用说明rawPricenumber \| [ number, number ] \| null—待格式化的原始价格单个数字展示单价格二元数组展示价格区间若数组元素含 0 则不渲染当与productDisplayPrice同时出现时数组形式的rawPrice优先级更高isSmallestUnitboolean—为true时rawPrice中的数字被解释为货币最小单位如美分的整数而非浮点金额对productDisplayPrice无效originalboolean—添加is-originalCSS 类呈现划线原价样式discountedboolean—添加is-discountedCSS 类呈现绿色折扣价样式currencyCodestring \| nullUSD货币代码ISO 4217。未设置或为undefined时回退到USD显式为null时组件什么都不渲染仅在使用rawPrice时生效classNamestring—追加到组件输出元素的 className 上isOnSaleboolean—为true时在价格旁显示 Sale 徽章对productDisplayPrice与displayFlatPrice无效taxTextstring—在价格旁渲染(X tax)文本X为传入值对productDisplayPrice与displayFlatPrice无效displayPerMonthNotationboolean—在价格旁显示 per month每月标注对productDisplayPrice与displayFlatPrice无效productDisplayPricestring \| TranslateResult—后端预格式化的价格字符串可含 HTML原样输出仅当rawPrice为数组时被忽略omitHeadingboolean—为true时渲染span而非默认的h4标题标签displayFlatPriceboolean—平铺展示价格不再把整数部分与小数部分拆成两个元素而是输出完整价格文本开启后多数格式化选项tax、sale、per-month、wrapper class失效priceDisplayWrapperClassNamestring—为每个价格渲染一个带该 class 的div包裹层对displayFlatPrice与productDisplayPrice无效isLargeCurrencyboolean—添加is-large-currency类以大字号渲染适用于大面额货币如韩元、印尼盾渲染优先级重要从render()的实现index.tsx#L36-L52可以看出两条明确的优先级规则productDisplayPrice优先只要productDisplayPrice有值、且rawPrice不是长度大于 1 的数组就直接原样输出productDisplayPrice忽略currencyCode、taxText、isOnSale、displayPerMonthNotation等所有格式化选项rawPrice数组覆盖当rawPrice是数组长度 ≥ 2时反过来忽略productDisplayPrice走完整的货币格式化流程。此外还有两个渲染为空的边界情况currencyCode为null且使用rawPrice→ 返回nullrawPrice为二元数组且其中包含0如[10, 0]→ 返回null避免渲染出$10-0这种荒谬的区间。这些规则全部有对应单元测试背书见下文测试验证一节。底层原理getCurrencyObject 如何完成货币本地化当走rawPrice分支时组件把格式化的重活委托给automattic/number-formatters的getCurrencyObject。从 packages/format-currency/src/index.ts 的实现可以看到注意number-formatters底层复用了该逻辑它利用Intl.NumberFormat将金额拆解成以下结构symbol货币符号如$、€、kr.、C$symbolPositionbefore或after决定符号在数字左侧还是右侧例如法语加拿大fr-CA环境下48 CAD渲染为48C$符号在右侧integer整数部分字符串已按语言习惯包含千分位分组如44,700fraction小数部分含小数点分隔符如.50hasNonZeroFraction布尔值标记小数部分是否非零sign符号如负数。PlanPrice 正是依据这些字段拼装出最终 DOM。以 HtmlPriceDisplay 为例整数部分放入span classplan-price__integer小数部分放入sup classplan-price__fraction且仅当hasNonZeroFraction为真时才渲染——这也是为什么44700DKK会渲染成kr.44,700而不会出现多余的.00货币符号放进sup classplan-price__currency-symbol位置由symbolPosition决定。isSmallestUnit 的换算isSmallestUnit意味着传入的是最小货币单位整数例如美分5001表示$50.01。测试用例 test/index.tsx#L40-L46 验证了PlanPrice rawPrice{ 5001 } isSmallestUnit /渲染为$50.01。这对处理分、仙等无小数的整数金额非常有用可以避免浮点运算误差。折扣展示与样式体系README 的核心使用建议是要突出价格已打折就用两个 PlanPrice 并排放在 flexbox 容器中import { PlanPrice } from automattic/components; export default class extends React.Component { static displayName MyPlanPrice; render() { return ( div span classNamemy-plan-price-with-flexbox PlanPrice rawPrice{ 99 } original / PlanPrice rawPrice{ 30 } discounted / /span span classNamemy-plan-price-with-flexbox PlanPrice rawPrice{ [ 132.2, 110.4 ] } original / PlanPrice rawPrice{ [ 99.99, 87 ] } discounted / /span /div ); } }上述示例完整来自 README.md可直接复制运行。样式的核心规则在 style.scss.plan-price.is-original使用中性浅色--color-neutral-light并通过::before伪元素绘制一条rotate(-16deg)的 2px 删除线--color-accent模拟经典的划线原价.plan-price.is-discounted使用成功色--color-success绿色突出折扣后的现价.plan-price__currency-symbol/.plan-price__fraction/.plan-price__tax-amount均以上标vertical-align: super呈现字号为$font-body-extra-small.plan-price__term每月标注的样式0.875rem字号左对齐。组件还会根据omitHeading决定外层标签默认渲染h4测试 test/index.tsx#L246-L268 验证了h4与span的切换所以在页面中它天然是一个语义化的价格标题。单元测试验证的行为契约packages/components/src/plan-price/test/index.tsx 使用testing-library/react jsdom 环境编写了 30 条用例基本锁定了组件的行为契约。以下是最值得注意的几条均可作为你在集成时对行为的确认依据零与区间rawPrice{ 0 }渲染$0rawPrice{ [10, 0] }不渲染$10-0L22-L69优先级rawPrice为数字时用productDisplayPricerawPrice为数组时反过来覆盖productDisplayPrice设置productDisplayPrice时currencyCode被忽略L71-L122货币currencyCodeEUR渲染€5.05undefined回退$null什么都不渲染DKK下整数44700无小数位、浮点44700.5显示.50L124-L159FlatPricedisplayFlatPrice下输出完整文本kr.44,700.50作为一个整体文本节点且忽略isOnSale、taxText、displayPerMonthNotationL161-L244符号位置en-US下 CAD 渲染为C$48符号在左fr-CA下渲染为48C$符号在右L354-L375CSS 类original/discounted/isLargeCurrency分别产生is-original、is-discounted、is-large-currency类L312-L352。在真实业务页面中的使用在client侧PlanPrice 被广泛用于套餐与产品价格展示。例如 Jetpack 产品商店的价格明细组件 client/my-sites/plans/jetpack-plans/product-store/pricing-breakdown/render-price.tsx 中import { PlanPrice } from automattic/components; // ... PlanPrice rawPrice{ price } currencyCode{ currencyCode } displayFlatPrice /它选择displayFlatPrice模式从产品数据中取出原始价格price与currencyCode由组件统一完成本地化格式化无需每个页面重复实现货币逻辑。类似的使用点还包括 client/my-sites/plans/jetpack-plans/product-lightbox/payment-plan.tsx、client/my-sites/plans/woo-express-plans-page/index.tsx 等。这印证了组件的设计初衷把价格格式化 折扣视觉表现收敛到一个组件里业务页面只关心给数字还是给字符串。常见问题与边界行为小结想要区间价格就传数组rawPrice{[ low, high ]}中间自动渲染为{{smallerPrice}}-{{higherPrice}}经由translate处理支持 i18n不要传 0 进区间数组会被当作无意义区间整体不渲染productDisplayPrice可以带 HTML组件用dangerouslySetInnerHTML原样输出因此只应传入可信的后端数据同时传两个 prop 时的选择单价格时productDisplayPrice生效区间时rawPrice生效语义化标题默认是h4在列表/段落内嵌场景请用omitHeading降级为span大面额货币日元、韩元、印尼盾等面额很大时用isLargeCurrency获得更小的字号对应样式表$font-title-large与is-large-currency类的配合。延伸阅读组件文档与示例packages/components/src/plan-price/README.md、docs/example.jsx、index.stories.jsx组件实现packages/components/src/plan-price/index.tsx样式packages/components/src/plan-price/style.scss测试packages/components/src/plan-price/test/index.tsx底层货币格式化工具packages/format-currency/src/index.ts 与 packages/format-currency/README.md赞分享前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载相关推荐如何利用IP-Adapter-FaceID革新旅游业虚拟导游与人脸定制服务完全指南如何利用IP Adapter FaceID革新旅游业虚拟导游与人脸定制服务完全指南 IP Adapter FaceID作为一款基于Stable Diffusi计算机视觉大模型Leantime 自托管项目管理完整指南部署、建项目、管任务一次跑通Leantime 自托管项目管理完整指南部署、建项目、管任务一次跑通 Leantime 是一个开源免费的项目管理系统把任务看板、里程碑时间线、个人待办和工作后端项目管理企业应用Godot 3 Demos最佳实践总结10个提升游戏开发效率的关键技巧Godot 3 Demos最佳实践总结10个提升游戏开发效率的关键技巧 Godot 3 Demos是一个为Godot游戏引擎提供数十个免费开源演示的项目涵盖上一篇GitHub_Trending/py/pytudes数据库集成SQLite与Python数据持久化下一篇终极指南如何利用agno事件总线实现智能体系统的高效解耦通信创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考