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