間選擇方案)
前端CMS【免費(fèi)下載鏈接】wp-calypsoThe JavaScript and API powered WordPress.com項(xiàng)目地址https://gitcode.com/gh_mirrors/wp/wp-calypso點(diǎn)擊查看免費(fèi)下載導(dǎo)讀本文圍繞 wp-calypsoWordPress.com 的 JavaScript 與 API 前端中的DateRange組件展開它基于 DatePicker 組件 提供「日歷 表單輸入 Trigger 按鈕 Popover」一體的日期區(qū)間選擇能力被大量用于統(tǒng)計(jì)、活動(dòng)日志等需要按時(shí)間范圍篩選數(shù)據(jù)的場(chǎng)景。讀完本文你將掌握DateRange的全部公開 Props 與 Render Props 用法、如何通過回調(diào)把日期數(shù)據(jù)交給父組件、如何限制可選區(qū)間以及從源碼角度理解其響應(yīng)式 Popover 布局、提交/回退/清空等內(nèi)部狀態(tài)機(jī)原理。DateRange 是什么DateRange是 wp-calypso 中用于展示并選擇一段日期范圍的 React 組件定義于 client/components/date-range/index.jsx。它的設(shè)計(jì)目標(biāo)是把「日期區(qū)間選擇」這件高頻需求封裝成開箱即用的整件自帶觸發(fā)器Trigger按鈕點(diǎn)擊后展開PopoverPopover 內(nèi)包含日歷底層使用 React Day Picker 風(fēng)格的 DatePicker與開始/結(jié)束日期表單輸入框可選地在日歷右側(cè)展示快捷區(qū)間Shortcuts菜單Popover 寬度充足時(shí)顯示雙日歷空間不足時(shí)自動(dòng)降級(jí)為單日歷、再不足時(shí)**堆疊stacked**顯示。組件通過localize( withLocalizedMoment( DateRange ) )包裹index.jsx 末行因此全部日期均按當(dāng)前 locale 格式化也接受原生Date或Moment兩種日期對(duì)象?;A(chǔ)用法組件按calypso/components/date-range路徑導(dǎo)入。以下是最小可用示例import DateRange from calypso/components/date-range; export default class DateRangeExample extends React.Component { render() { return DateRange /; } }沒有任何 Props 時(shí)組件默認(rèn)預(yù)選「今天往前推 1 個(gè)月」到「今天」這段范圍并渲染一個(gè)標(biāo)準(zhǔn)的 Trigger 按鈕點(diǎn)擊按鈕即可在 Popover 中重新選擇區(qū)間。在實(shí)際業(yè)務(wù)中通常需要把選擇結(jié)果交還給父組件維護(hù)。推薦的常見組合對(duì)應(yīng) README 中「General guidelines」的建議import DateRange from calypso/components/date-range; export default class DateFilter extends React.Component { state { startDate: null, endDate: null }; onDateCommit ( startDate, endDate ) { // 用戶點(diǎn)擊 Apply 后這里拿到最終確定的時(shí)間范圍 this.setState( { startDate, endDate } ); }; render() { const { startDate, endDate } this.state; return ( DateRange selectedStartDate{ startDate } selectedEndDate{ endDate } onDateCommit{ this.onDateCommit } displayShortcuts / ); } }Props 全解README 中以表格形式給出了完整 Props 清單帶*的為必填項(xiàng)DateRange當(dāng)前所有公開 Props 均非必填。以下為完整繼承并補(bǔ)充實(shí)現(xiàn)細(xì)節(jié)的版本NameTypeDefaultDescriptionselectedStartDateDate或Moment今天減 1 個(gè)月希望日歷 UI 中默認(rèn)預(yù)選的區(qū)間首日selectedEndDateDate或Moment今天希望日歷 UI 中默認(rèn)預(yù)選的區(qū)間末日firstSelectableDateDate或Momentundefined用戶可選日期范圍的第一天更早的日期被禁用lastSelectableDateDate或Momentundefined用戶可選日期范圍的最后一天更晚的日期被禁用isCompactBooleanfalse決定 Trigger 是否用compact布局渲染如需更精細(xì)控制 Trigger建議改用下方的 Render Props 覆寫onDateCommit(startDate, endDate)Functionundefined日期被提交點(diǎn)擊 Apply時(shí)調(diào)用的回調(diào)onDateSelect(startDate, endDate)Functionundefined日期被選中但尚未提交未點(diǎn) Apply時(shí)調(diào)用的回調(diào)triggerText(startDateText, endDateText)Functionundefined生成 Trigger 按鈕文案的函數(shù)參數(shù)為MM/DD/YYYY或 locale 對(duì)應(yīng)格式的開始/結(jié)束日期文本displayShortcutsBooleanfalse是否在日歷旁顯示快捷區(qū)間菜單useArrowNavigationBooleanfalse是否用左右箭頭導(dǎo)航替代「月份標(biāo)簽按鈕」來切換日歷月份overlaynodenull若傳入則渲染在日歷與日期輸入框之上通常用于「鎖住」選擇器的提示層customTitleString為 Popover 提供自定義替代標(biāo)題源碼中 index.jsx 的 propTypes 還暴露了 README 未細(xì)列的若干內(nèi)部聯(lián)動(dòng) Props它們同樣是公開 APINameTypeDefaultDescriptionselectedShortcutIdStringnull當(dāng)前選中的快捷區(qū)間 id配合 Shortcuts 使用showTriggerClearBooleantrue是否在 Trigger 上顯示「清空」按鈕onShortcutClickFunctionundefined快捷區(qū)間點(diǎn)擊時(shí)的跟蹤/跳轉(zhuǎn)回調(diào)見下文「快捷區(qū)間」一節(jié)shortcutListArray默認(rèn)快捷區(qū)間自定義快捷區(qū)間列表覆蓋 use-shortcuts 內(nèi)置項(xiàng)trackExternalDateChangesBooleanfalse為true時(shí)每次打開 Popover 都會(huì)同步外部傳入的selectedStartDate/selectedEndDaterootClassString附加到組件根節(jié)點(diǎn)的 classfocusedMonthDatenull日歷初始聚焦月份兩個(gè)日期回調(diào)的區(qū)別onDateSelect 與 onDateCommit這是最容易混淆的一對(duì) Props建議在實(shí)際開發(fā)中按「預(yù)覽」與「確定」來理解onDateSelect(startDate, endDate)在日歷上點(diǎn)選日期或輸入框失焦產(chǎn)生新范圍時(shí)立即觸發(fā)見 index.jsx 的 handleDateRangeChange。此時(shí)改動(dòng)只是「草稿」用戶若關(guān)閉 Popover 而未 Apply改動(dòng)會(huì)被回退。onDateCommit(startDate, endDate, selectedShortcutId)僅在點(diǎn)擊Apply或清空日期、回退日期時(shí)觸發(fā)是真正需要持久化的時(shí)機(jī)見 commitDates。實(shí)戰(zhàn)建議需要即時(shí)反饋的預(yù)覽性 UI 用onDateSelect需要寫回全局狀態(tài)/接口的用onDateCommit二者可同時(shí)使用。Render Props覆寫組件四大區(qū)域當(dāng)默認(rèn)的 Trigger、Header、Footer、Inputs 不夠用、需要重度定制外觀時(shí)README 推薦使用 Render Props 模式。四個(gè)覆寫入口均接收與默認(rèn)子組件完全相同的 props 對(duì)象NameTypeDefaultDescriptionrenderTrigger(props)Functionundefined覆寫默認(rèn)的DateRangeTrigger組件renderHeader(props)Functionundefined覆寫默認(rèn)的DateRangeHeader組件renderFooter(props)Functionundefined覆寫默認(rèn)的DateRangeFooter組件renderInputs(props)Functionundefined覆寫默認(rèn)的DateRangeInputs組件源碼的 defaultProps 給出了默認(rèn)實(shí)現(xiàn)即這四個(gè)渲染函數(shù)的返回值例如renderTrigger: ( props ) DateRangeTrigger { ...props } /, renderFooter: ( props ) DateRangeFooter { ...props } /,以覆寫 Footer 為例例如把 Apply / Cancel 換成自定義按鈕文案或增加一個(gè)「導(dǎo)出」按鈕DateRange selectedStartDate{ startDate } selectedEndDate{ endDate } renderFooter{ ( props ) ( div classNamemy-custom-footer button onClick{ props.onApplyClick }確定區(qū)間/button button onClick{ props.onCancelClick }取消/button /div ) } /其中onApplyClick對(duì)應(yīng)內(nèi)部commitDatesonCancelClick對(duì)應(yīng)closePopoverAndRevert回退到上一次提交的日期footerProps里還有isApplyDisabled用于在開始/結(jié)束日期二者只有一個(gè)時(shí)禁用 Apply見 renderPopover 中 footerProps 的構(gòu)造。覆寫 Trigger 時(shí)接收到的 props 包括startDate、endDate、startDateText、endDateText、buttonRefPopover 定位錨點(diǎn)、onTriggerClick、onClearClick、triggerText、isCompact與showClearBtn可據(jù)此自定義按鈕外觀而不破壞 Popover 的定位邏輯。限制可選日期范圍README 的 General guidelines 明確推薦用firstSelectableDate與lastSelectableDate兩個(gè) Props 定義可選項(xiàng)的上下界可只傳其一。底層實(shí)現(xiàn)分兩層禁用日歷天在 date-range-picker.tsx 的 getDisabledDaysConfig 中把上下界轉(zhuǎn)換為 React Day Picker 的disabledDays數(shù)組{ before: ..., after: ... }同時(shí)通過fromMonth/toMonth限制日歷可翻頁的月份范圍校驗(yàn)與鉗制初始化時(shí) clampDateToRange 會(huì)把傳入的預(yù)選日期鉗制到可選區(qū)間內(nèi)點(diǎn)選時(shí) isValidDate 會(huì)拒絕早于01/01/1970、早于firstSelectableDate或晚于lastSelectableDate的日期。示例——只允許選擇「今年 1 月 1 日」到「今天」const firstSelectableDate moment().startOf( year ); const lastSelectableDate moment(); DateRange selectedStartDate{ moment().subtract( 7, days ) } selectedEndDate{ moment() } firstSelectableDate{ firstSelectableDate } lastSelectableDate{ lastSelectableDate } onDateCommit{ this.onDateCommit } /此外若傳入的selectedStartDate晚于selectedEndDate組件會(huì)自動(dòng)翻轉(zhuǎn)二者構(gòu)造函數(shù)里通過數(shù)組解構(gòu)交換index.jsx L110-L113日歷層還通過useEffect做了二次兜底date-range-picker.tsx L134-L138??旖輩^(qū)間Shortcuts當(dāng)displayShortcuts為true時(shí)Popover 右側(cè)會(huì)渲染快捷區(qū)間菜單shortcuts.tsx。默認(rèn)快捷區(qū)間定義于 use-shortcuts.ts以站點(diǎn)時(shí)區(qū)getMomentSiteZone的「今天」為基準(zhǔn)動(dòng)態(tài)計(jì)算| id | 文案 | 區(qū)間 | | -- | ---- | ---- | |today| Today | 今天 | |last_7_days| Last 7 Days | 今天往前 6 天 | |last_30_days| Last 30 Days | 今天往前 29 天 | |month_to_date| Month to date | 本月 1 號(hào)到今天 | |last_12_months| Last 12 months | 往前 11 個(gè)月的月初到今天 | |year_to_date| Year to date | 今年 1 月 1 號(hào)到今天 | |last_3_years| Last 3 years | 往前 2 年的年初到今天 |每個(gè)快捷項(xiàng)都是{ id, label, startDate, endDate, period }結(jié)構(gòu)period取自DATERANGE_PERIODhour/day/week/month/year。組件會(huì)通過findShortcutForRange反查當(dāng)前選中的日期區(qū)間是否恰好命中某個(gè)快捷項(xiàng)use-shortcuts.ts L18-L44從而高亮顯示也可用shortcutListProp 傳入完全自定義的列表。點(diǎn)選快捷項(xiàng)時(shí)handleShortcutClick會(huì)把closePopoverAndCommit提交并關(guān)閉和closePopover僅關(guān)閉、不提交也不回退兩個(gè)句柄交給onShortcutClick由業(yè)務(wù)方?jīng)Q定快捷項(xiàng)點(diǎn)擊后的行為例如「All time」這類需要跳轉(zhuǎn)其他頁面的快捷項(xiàng)應(yīng)走僅關(guān)閉的路徑避免回退觸發(fā)多余的onDateCommit參見 index.jsx L525-L531。當(dāng)傳入overlay如付費(fèi)墻提示時(shí)快捷菜單處于locked狀態(tài)點(diǎn)擊不會(huì)改變?nèi)掌趕hortcuts.tsx L60-L68。源碼視角Popover 的自適應(yīng)布局README 特別強(qiáng)調(diào)Popover 打開時(shí)默認(rèn)顯示雙日歷當(dāng) Trigger 周圍可用的內(nèi)容區(qū)域太窄時(shí)會(huì)自動(dòng)降級(jí)為單日歷仍不夠則把快捷菜單堆疊到下方。這一機(jī)制由 index.jsx 實(shí)現(xiàn)打開 Popover 時(shí)getOptimisticPopoverLayoutState先按「雙日歷、不堆疊」的樂觀布局渲染L471-L477內(nèi)容掛載后settleLayout檢測(cè)contentElement.scrollWidth clientWidth 1忽略亞像素舍入產(chǎn)生的 1px只要溢出就只做「降級(jí)」先是numberOfMonths從 2 降到 1再是isPopoverStacked置為trueL487-L504布局寬度來自getContentAreaElement()——即 Trigger 按鈕向上找到最近的.main、#wpcontent或.layout__content容器取其寬度并扣除兩側(cè)POPOVER_GUTTER 16pxL456-L469窗口resize時(shí)通過 250ms 的debounce重新計(jì)算恢復(fù)樂觀布局L138-L140??梢娊M件對(duì)「窄屏/嵌入 wp-admin」場(chǎng)景做了專門適配——這正是它被用于統(tǒng)計(jì)頁、活動(dòng)日志篩選條等寬度多變區(qū)域的原因。日期輸入框的交互同樣值得注意失焦blur時(shí)用 locale 對(duì)應(yīng)的L格式解析文本getLocaleDateFormat無效日期直接放棄聚焦結(jié)束時(shí)handleInputFocus在雙日歷模式下會(huì)把結(jié)束日期輸入框?qū)?yīng)的焦點(diǎn)月份前移一個(gè)月讓雙日歷的第二格恰好顯示目標(biāo)月份。區(qū)間選擇的內(nèi)部算法日歷上每次點(diǎn)選如何推進(jìn)區(qū)間答案在 date-range-picker.tsx 與 utils.ts 的 addDayToRange點(diǎn)選日期先被startOf(day)歸一化并校驗(yàn)若當(dāng)前還沒有任何端點(diǎn)把點(diǎn)選的日期作為from若只有一個(gè)端點(diǎn)用點(diǎn)選日補(bǔ)齊另一端并保持兩者有序點(diǎn)選日在錨點(diǎn)之前則作from否則作to若區(qū)間已完整重新以點(diǎn)選日開啟一個(gè)新區(qū)間from置為新日期、to置空。隨后date-range-picker.tsx會(huì)基于from/to構(gòu)造 React Day Picker 的modifiersstart、end、range-start、range-end、range與selectedDays數(shù)組讓被選中的區(qū)間以高亮樣式呈現(xiàn)在日歷中。整個(gè)「選中-未提交」?fàn)顟B(tài)只存在于組件內(nèi)部 state只有commitDates才會(huì)通過onDateCommit把它同步給父組件——這與前文介紹的提交/回退語義完全閉環(huán)。相關(guān)組件DatePickerDateRange的底層日期選擇實(shí)現(xiàn)單日/多日選擇、事件標(biāo)記、initialMonth、selectedDay等 PropsDateRange在其之上封裝了區(qū)間選擇邏輯與 Popover 交互層localized-moment為組件注入按 locale 與站點(diǎn)時(shí)區(qū)工作的moment實(shí)例DateRange通過withLocalizedMoment獲得該能力組件實(shí)際使用示例可參考 client/dashboard/app/hooks/use-date-range.ts 與 client/my-sites/activity/filterbar/date-range-selector.jsx它們展示了如何把DateRange接入頁面篩選邏輯。小結(jié)DateRange是 wp-calypso 中一個(gè)「小而完整」的區(qū)間選擇組件對(duì)外暴露清晰的 Props 與 Render Props 接口對(duì)內(nèi)則包含了日期鉗制、locale 格式化、響應(yīng)式 Popover 降級(jí)、快捷區(qū)間與提交/回退狀態(tài)機(jī)等成熟實(shí)現(xiàn)。無論是直接嵌入使用還是通過四個(gè)渲染入口深度定制其 API 設(shè)計(jì)與源碼結(jié)構(gòu)都值得在構(gòu)建類似「日歷區(qū)間選擇」業(yè)務(wù)時(shí)參考。贊分享前端CMS【免費(fèi)下載鏈接】wp-calypsoThe JavaScript and API powered WordPress.com項(xiàng)目地址https://gitcode.com/gh_mirrors/wp/wp-calypso點(diǎn)擊查看免費(fèi)下載相關(guān)推薦Apache Beam Go SDK 聚合 Kata 實(shí)戰(zhàn)使用 stats.Mean 計(jì)算 PCollection 均值A(chǔ)pache Beam Go SDK 聚合 Kata 實(shí)戰(zhàn)使用 stats.Mean 計(jì)算 PCollection 均值 本文基于 Apache Beam 倉批處理流處理大數(shù)據(jù)wp-calypso Post Likes 組件開發(fā)指南從基礎(chǔ)渲染到 Popover 交互的完整實(shí)現(xiàn)wp calypso Post Likes 組件開發(fā)指南從基礎(chǔ)渲染到 Popover 交互的完整實(shí)現(xiàn) 本指南圍繞 wp calypso 倉庫中 client/前端CMS基于 wp-calypso 的 FormattedDate 組件本地化日期時(shí)間格式化的完整實(shí)踐指南基于 wp calypso 的 FormattedDate 組件本地化日期時(shí)間格式化的完整實(shí)踐指南 wp calypso 作為 WordPress.com 的前端CMS上一篇DLSS Swapper 新手指南5 分鐘把老游戲的 DLSS 升到最新版下一篇使用 VSCode.dev 從零構(gòu)建并部署個(gè)人簡(jiǎn)歷網(wǎng)站W(wǎng)eb-Dev-For-Beginners 第 8 課完整實(shí)戰(zhàn)指南創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考