vant icon indicating copy to clipboard operation
vant copied to clipboard

fix(Calendar): fix getInitialDate function error

Open pany-ang opened this issue 1 year ago • 7 comments

getInitialDate 方法的形参在接收到一个长度为 1 的数组时,将可能发生意料之外的情况。

原方法如下,如果入参为 [new Date(2025, 7, 21)],并且日历 typerange 时:

const getInitialDate = (defaultDate = props.defaultDate) => {
      // ...

      if (type === 'range') {
        if (!Array.isArray(defaultDate)) {
          defaultDate = [];
        }

        const min = minDate.value;
        const max = maxDate.value;

        const start = limitDateRange( // 这儿可能获得 new Date(2025, 7, 21)
          defaultDate[0] || now,
          min,
          max ? (allowSameDay ? max : getPrevDay(max)) : undefined,
        );

        const end = limitDateRange( // 这儿可能获得 now
          defaultDate[1] || (allowSameDay ? now : getNextDay(now)),
          min ? (allowSameDay ? min : getNextDay(min)) : undefined,
        );

        return [start, end]; // 最终可能获得 [new Date(2025, 7, 21), now]
      }

      // ...
    };

最终输出的结果 [new Date(2025, 7, 21), now] 对于今天来说就是 [new Date(2025, 7, 21), new Date(2024, 7, 21)],也就代表着开始时间大于结束时间了。

如果业务层没有兜底这种 「开始时间大于结束时间」就会导致意料之外 BUG。

组件直接进行兜底是一个不错的选择

if (type === 'range') {
        if (!Array.isArray(defaultDate) || defaultDate.length === 1) { // 截获长度为 1 的数组
          defaultDate = [];
        }

pany-ang avatar Aug 21 '24 13:08 pany-ang

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Project coverage is 89.69%. Comparing base (8aeeba4) to head (9f37304). Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #13075      +/-   ##
==========================================
+ Coverage   89.61%   89.69%   +0.07%     
==========================================
  Files         257      257              
  Lines        6992     6994       +2     
  Branches     1725     1726       +1     
==========================================
+ Hits         6266     6273       +7     
+ Misses        384      380       -4     
+ Partials      342      341       -1     

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

codecov-commenter avatar Aug 21 '24 13:08 codecov-commenter

两个触发条件:

watch(
      () => [props.type, props.minDate, props.maxDate, props.switchMode],
      () => reset(getInitialDate(currentDate.value)),
    );
  1. 默认给一个长度为 1 的 defaultDate

pany-ang avatar Aug 21 '24 13:08 pany-ang

看了下提交历史,是有意这么实现的

inottn avatar Aug 21 '24 14:08 inottn

看了下提交历史,是有意这么实现的

以前这么实现是有什么好处吗

pany-ang avatar Aug 21 '24 15:08 pany-ang

20240822101728_rec_

pany-ang avatar Aug 22 '24 02:08 pany-ang

defaultDate 数组「仅包含一项」是允许的,如果需要预防错误的输入,可以仅对错误输入进行重置,而不是对所有情况进行重置

chenjiahan avatar Aug 24 '24 01:08 chenjiahan

defaultDate 数组「仅包含一项」是允许的,如果需要预防错误的输入,可以仅对错误输入进行重置,而不是对所有情况进行重置

针对你的建议,现将代码更新为「长度为 1 并且开始日期大于今日」时视为错误输入

      if (type === 'range') {
        if (!Array.isArray(defaultDate)) {
          defaultDate = [];
        }

        if (defaultDate.length === 1 && compareDay(defaultDate[0], now) === 1) { // 单独对数组长度为 1 的情况进行处理
          defaultDate = [];
        }

可以看看是否已经满足~

pany-ang avatar Aug 27 '24 07:08 pany-ang

可以补充一下单元测试

inottn avatar Aug 30 '24 16:08 inottn

已添加

pany-ang avatar Aug 31 '24 06:08 pany-ang