- 前端
- UI组件
【免费下载链接】rsuite
🧱 A suite of React components .
导读
showWeekNumbers是 rsuiteDateRangePicker组件中用于在日历面板左侧显示"周数"列的开关属性。本文以 show-week-numbers.md 演示片段 为骨架,完整讲解其用法、与isoWeek/weekStart的协同关系、周数计算规则(普通周w与 ISO 周I),并结合 GridRow.tsx 等源码与测试用例,说明周数列从"属性传入 → 上下文传递 → 表头占位 → 行内渲染 → 样式呈现"的完整实现链路。读完本文,你将能独立在 rsuite 项目中开启周数显示,并理解其周数编号遵循哪套标准、受哪些属性影响。
一分钟上手:在 DateRangePicker 中开启周数
原文档提供的演示片段非常简洁,核心用法就是在DateRangePicker上设置一个布尔属性:
import { DateRangePicker } from 'rsuite'; const App = () => ( <> <DateRangePicker showWeekNumbers /> </> ); ReactDOM.render(<App />, document.getElementById('root'));从 en-US 组件文档的 Props 表 可以看到该属性的官方定义:
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
showWeekNumbers | boolean | — | 是否显示周数(Whether to show week numbers) |
要点:
- 属性为可选的布尔开关,不传则默认不显示周数列;
- 它同时适用于
DateRangePicker与DatePicker(后者在 show-week-numbers.md 演示片段 中还有w={200}指定宽度);本文聚焦DateRangePicker; showWeekNumbers只决定"周数列是否出现",周数的编号标准与每周起始日由isoWeek、weekStart、locale决定,三者缺一不可理解。
开启后,日历面板左侧会出现一列宽度约30px、背景与正文区略有区分的数字列,每一行(即一周)显示该周在一年中的序号。
周数列的外观:样式层如何呈现
周数列的视觉样式在 src/Calendar/styles/index.scss 中定义,核心类为rs-calendar-table-cell-week-number:
.rs-calendar-table-cell-week-number { display: table-cell; min-width: 30px; padding: var(--rs-calendar-table-cell-padding); text-align: center; vertical-align: middle; color: var(--rs-text-secondary); background-color: var(--rs-bg-well); font-size: var(--rs-font-size-xs); }可以归纳出以下实现事实:
- 周数列作为
table-cell参与日历的表格布局,最小宽度30px,文字水平居中、垂直居中对齐; - 使用次级文本色
--rs-text-secondary与底色--rs-bg-well,与日期单元格形成视觉层级区分,字号为--rs-font-size-xs(小号字体),整体呈现为弱化的辅助信息列; - 表格第一行与最后一行(即整个面板的第一周与最后一周)的周数单元格还会通过 index.scss 中的圆角规则 应用
--rs-radius-md圆角,保持与面板整体轮廓一致。
周数如何计算:普通周w与 ISO 周I
周数编号并非简单从 1 数到 52,它与"一周从哪天开始"强相关。在 GridRow.tsx 中,周数通过 date-fns 的format按两种模式计算:
const { firstWeekContainsDate } = locale?.dateLocale?.options ?? {}; // ISO week starts on Monday const date = isoWeek ? addDays(startingDate, 1) : startingDate; const week = format(new Date(date.year, date.month - 1, date.day), isoWeek ? 'I' : 'w', { locale: locale?.dateLocale, firstWeekContainsDate, weekStartsOn: weekStart });关键逻辑说明:
isoWeek为false(默认):使用 date-fns 的'w'格式符计算普通周数,weekStartsOn传入weekStart的值,firstWeekContainsDate取自 locale 的dateLocale.options;isoWeek为true:使用'I'格式符计算ISO 8601 周数,并且由于 ISO 标准规定每周从星期一开始,源码在计算前对日期做了addDays(startingDate, 1)的偏移调整,确保周号归属正确;- 也就是说,周数列显示的数字会随着
isoWeek、weekStart以及 locale 设置的不同而改变,同一个日期在不同配置下可能属于不同的"周号"。
起始日如何决定:isoWeek 与 weekStart 的优先级
每周从哪天开始,直接影响周数的划分。在 useCalendar.ts 中有一套明确的计算优先级:
const weekStart = useMemo(() => { // If weekStartProp is explicitly provided, use it if (typeof weekStartProp !== 'undefined') { return weekStartProp; } // If using ISO week, start on Monday (1) else if (isoWeek) { return 1; } // If locale specifies a weekStartsOn option, use it else if (locale?.dateLocale?.options?.weekStartsOn !== undefined) { return locale.dateLocale.options.weekStartsOn; } // Default to Sunday (0) if no other condition is met return 0; }, [weekStartProp, isoWeek, locale?.dateLocale?.options?.weekStartsOn]);优先级从高到低依次是:
- 显式传入的
weekStart(取值0~6,0为星期日,与 Props 表 一致); isoWeek为true时强制weekStart = 1(星期一),此时weekStart被忽略(文档 Props 表中注明:"如果设置了isoWeek,则忽略此属性");- locale 中
dateLocale.options.weekStartsOn的本地化设置; - 兜底默认
0(星期日)。
值得注意的联动关系:
- 若只设置
showWeekNumbers而不设置任何起始日,周数列默认按"星期日为一周第一天"的规则编号; - 若希望周数与"周一为一周开始"的 ISO 8601 惯例一致,应同时设置
isoWeek;例如 hover-range.md 演示片段 中"选择整周"示例,就通过hoverRange="week" isoWeek保证按 ISO 标准选周; - 若业务上以星期三为一周开始,可设置
weekStart={3},周数列会同步按该规则编号。
从属性到界面:周数列的完整实现链路
showWeekNumbers在 rsuite 中的传递链路清晰,可以从源码逐一验证:
1. 属性声明与透传
在 DateRangePicker.tsx 中声明showWeekNumbers?: boolean,并在渲染弹出面板时(DateRangePicker.tsx)将其与isoWeek、weekStart等一起组装进calendarProps,传入日期范围选择器内部的Calendar。
2. 进入日历上下文
DateRangePicker/Calendar.tsx 将showWeekNumbers等属性透传给通用日历容器CalendarContainer,最终写入CalendarProvider提供的上下文。上下文类型定义见 CalendarProvider.ts,其中明确注释该字段含义为"是否显示周数"。
3. 表头留出空列
开启后,表头行会在每周列标题(Su/Mo/Tu/We/Th/Fr/Sa)之前渲染一个空的占位列,见 GridHeaderRow.tsx:
{showWeekNumbers && <div className={prefix('header-cell')} role="columnheader" />}对应测试 CalendarGridHeaderRow.spec.tsx 验证:当showWeekNumbers: true时,表头行应包含 8 个子节点(1 个空占位列 + 7 个星期标题列)。
4. 数据行渲染周数
每个数据行在渲染 7 个日期单元格之前,先渲染周数单元格,见 GridRow.tsx:
{showWeekNumbers && ( <div role="rowheader" aria-label={`Week ${week}`} className={prefix('cell-week-number')}> {week} </div> )}这里同时体现了无障碍设计:周数单元格带有role="rowheader"与aria-label="Week N",辅助技术可以读取每行的周号。此外,整个行结构使用role="row",日期/表头单元格使用role="columnheader",周数列与星期标题列共享同一表格布局。
与其他属性搭配的实战组合
结合组件文档与其他演示片段,showWeekNumbers常见的搭配方式如下:
| 组合意图 | 配置示例 | 说明 |
|---|---|---|
| 默认周数(周日为起点) | <DateRangePicker showWeekNumbers /> | 使用 locale 默认规则,通常为周日起始 |
| ISO 周数(周一为起点) | <DateRangePicker showWeekNumbers isoWeek /> | 周数与 ISO 8601 标准一致 |
| 自定义每周起点 | <DateRangePicker showWeekNumbers weekStart={3} /> | 如周三为一周第一天,周号随之重排 |
| 整周选择 + 周数 | <DateRangePicker showWeekNumbers hoverRange="week" isoWeek ranges={[]} /> | 配合 hover-range 演示,按周选择并同步显示 ISO 周号 |
需要注意的边界与前提:
- 当
isoWeek为true时,weekStart会被忽略(强制为1),因此上述第二、三种组合不应同时生效,实际以isoWeek为准; showWeekNumbers仅影响日历面板内部,不影响DateRangePicker输入框中的格式化文本(format属性);- 周数列占用一列表格宽度,若同时设置
showOneCalendar,单日历面板同样会渲染周数列,布局由 DateRangePicker.tsx 中的面板样式 统一控制。
总结
showWeekNumbers是一个轻量但涉及"周号语义"的开关属性,其背后完整依赖 rsuite 日历体系的三个组成部分:
- 属性透传层:
DateRangePicker→Calendar→CalendarContainer→CalendarProvider上下文(DateRangePicker.tsx); - 周数计算层:基于
isoWeek在 date-fns 的'w'与'I'格式符之间切换,并受weekStart、locale 影响(GridRow.tsx); - 呈现层:表头空占位列 + 行内
rs-calendar-table-cell-week-number单元格,配合rowheader角色保证无障碍(GridHeaderRow.tsx、index.scss)。
若你的业务需要展示"第几周"信息(如排班、报表、项目管理周报),直接在DateRangePicker上开启showWeekNumbers即可;若要周号符合国际惯例,请务必同时开启isoWeek,避免周日起始的默认规则带来周号偏差。
- 前端
- UI组件
【免费下载链接】rsuite
🧱 A suite of React components .
相关推荐
rsuite DatePicker 周数显示(showWeekNumbers)实战指南:从属性用法到源码实现
rsuite DatePicker 周数显示(showWeekNumbers)实战指南:从属性用法到源码实现 导读 showWeekNumbers 是 rsui
前端UI组件rsuite DatePicker 的 isoWeek 属性:启用 ISO 8601 周历显示与周编号
rsuite DatePicker 的 isoWeek 属性:启用 ISO 8601 周历显示与周编号 在 rsuite 的日期选择组件体系中, DatePic
前端UI组件使用 RSuite Calendar 定制周起始日:weekStart、isoWeek 与 showWeekNumbers 详解
使用 RSuite Calendar 定制周起始日:weekStart、isoWeek 与 showWeekNumbers 详解 本文基于 RSuite 日历组
前端UI组件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考