From cc0b60509af695e94a5d6a1ec2111613f76e2f84 Mon Sep 17 00:00:00 2001 From: mengxiong10 <15623530290@163.com> Date: Fri, 5 Feb 2021 18:25:38 +0800 Subject: [PATCH] refactor: range on hover use provide --- __test__/calendar-range.test.js | 34 +++++++++++++--------- src/calendar/calendar-panel.js | 4 --- src/calendar/calendar-range.js | 50 ++++++++++++++++----------------- src/calendar/table-date.vue | 16 ++++++++++- src/style/index.scss | 1 + 5 files changed, 61 insertions(+), 44 deletions(-) diff --git a/__test__/calendar-range.test.js b/__test__/calendar-range.test.js index 3882b3e..da90e8b 100644 --- a/__test__/calendar-range.test.js +++ b/__test__/calendar-range.test.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import { parse } from 'date-fns'; import CalendarRange from '../src/calendar/calendar-range'; import CalendarPanel from '../src/calendar/calendar-panel'; @@ -10,19 +11,25 @@ afterEach(() => { describe('CalendarRange', () => { it('feat: correct classes', () => { + const start = new Date(2019, 9, 30); + const end = new Date(2019, 10, 2); wrapper = mount(CalendarRange, { propsData: { - value: [new Date(2019, 9, 30), new Date(2019, 10, 2)], + value: [start, end], }, }); - const activeTds = wrapper.findAll('.mx-table-date .active'); - const rangeTds = wrapper.findAll('.mx-table-date .in-range'); - expect(activeTds.length).toBe(2); - expect(activeTds.at(0).text()).toBe('30'); - expect(activeTds.at(1).text()).toBe('2'); - expect(rangeTds.length).toBe(2); - expect(rangeTds.at(0).text()).toBe('31'); - expect(rangeTds.at(1).text()).toBe('1'); + const tds = wrapper.findAll('.mx-table-date td'); + + for (let i = 0; i < tds.length; i++) { + const td = tds.at(i); + const { title } = td.element; + const cell = parse(title, 'yyyy-MM-dd', new Date()).getTime(); + if (cell > start.getTime() && cell < end.getTime()) { + expect(td.classes()).toContain('in-range'); + } else { + expect(td.classes()).not.toContain('hover-in-range'); + } + } }); it('feat: click range', async () => { @@ -87,13 +94,12 @@ describe('CalendarRange', () => { defaultValue: new Date(2019, 9, 1), }, }); - expect(wrapper.vm.calendars).toEqual([new Date(2019, 9, 1), new Date(2019, 10, 1)]); const tds = wrapper.findAll('.mx-table-date td'); - await tds.at(2).trigger('click'); + await tds.at(10).trigger('click'); await tds.at(60).trigger('mouseenter'); for (let i = 0; i < tds.length; i++) { - if (i > 2 && i < 60) { + if (i > 10 && i < 60) { expect(tds.at(i).classes()).toContain('hover-in-range'); } else { expect(tds.at(i).classes()).not.toContain('hover-in-range'); @@ -104,10 +110,10 @@ describe('CalendarRange', () => { // hover to back await tds.at(60).trigger('click'); - await tds.at(2).trigger('mouseenter'); + await tds.at(10).trigger('mouseenter'); for (let i = 0; i < tds.length; i++) { - if (i > 2 && i < 60) { + if (i > 10 && i < 60) { expect(tds.at(i).classes()).toContain('hover-in-range'); } else { expect(tds.at(i).classes()).not.toContain('hover-in-range'); diff --git a/src/calendar/calendar-panel.js b/src/calendar/calendar-panel.js index ad35293..f9dec48 100644 --- a/src/calendar/calendar-panel.js +++ b/src/calendar/calendar-panel.js @@ -163,9 +163,6 @@ export default { handleSelectDate(date) { this.emitDate(date, this.type === 'week' ? 'week' : 'date'); }, - handleMouseEnter(cell) { - this.$emit('mouseenter', cell); - }, getMonthCellDate(month) { return createDate(this.calendarYear, month); }, @@ -262,7 +259,6 @@ export default { onSelect={this.handleSelectDate} onChangepanel={this.handelPanelChange} onChangecalendar={this.handleCalendarChange} - onMouseenter={this.handleMouseEnter} /> ); }, diff --git a/src/calendar/calendar-range.js b/src/calendar/calendar-range.js index dbef51b..7cfdb88 100644 --- a/src/calendar/calendar-range.js +++ b/src/calendar/calendar-range.js @@ -4,6 +4,12 @@ import { getValidDate, isValidDate, isValidRangeDate, startOfMonth } from '../ut export default { name: 'CalendarRange', components: { CalendarPanel }, + provide() { + return { + onDateMouseEnter: this.onDateMouseEnter, + onDateMouseLeave: this.onDateMouseLeave, + }; + }, inject: { prefixClass: { default: 'mx', @@ -66,10 +72,10 @@ export default { this.innerValue = [date, new Date(NaN)]; } }, - handleCellMouseEnter(cell) { + onDateMouseEnter(cell) { this.hoveredValue = cell; }, - handleRangeMouseLeave() { + onDateMouseLeave() { this.hoveredValue = null; }, emitDate(dates, type) { @@ -107,27 +113,26 @@ export default { }, getRangeClasses(cellDate, currentDates, classnames) { const classes = [].concat(this.getClasses(cellDate, currentDates, classnames)); - if ( - currentDates.length === 2 && - !/disabled|active|not-current-month/.test(classnames) && - cellDate.getTime() > currentDates[0].getTime() && - cellDate.getTime() < currentDates[1].getTime() - ) { - classes.push('in-range'); - } else if ( - currentDates.length === 1 && - this.hoveredValue && - !/disabled|active/.test(classnames) - ) { - let min = this.hoveredValue.getTime(); - let max = currentDates[0].getTime(); + if (/disabled|active/.test(classnames)) return classes; + + const inRange = (data, range, fn = v => v.getTime()) => { + const value = fn(data); + let [min, max] = range.map(fn); if (min > max) { [min, max] = [max, min]; } - if (cellDate.getTime() > min && cellDate.getTime() < max) { - classes.push('hover-in-range'); - } + return value > min && value < max; + }; + if (currentDates.length === 2 && inRange(cellDate, currentDates)) { + return classes.concat('in-range'); + } + if ( + currentDates.length === 1 && + this.hoveredValue && + inRange(cellDate, [currentDates[0], this.hoveredValue]) + ) { + return classes.concat('hover-in-range'); } return classes; @@ -147,17 +152,12 @@ export default { const on = { select: this.handleSelect, 'update:calendar': index === 0 ? this.updateStartCalendar : this.updateEndCalendar, - mouseenter: this.handleCellMouseEnter, }; return ; }); const { prefixClass } = this; - return ( -
- {calendarRange} -
- ); + return
{calendarRange}
; }, }; diff --git a/src/calendar/table-date.vue b/src/calendar/table-date.vue index 220a0eb..615843c 100644 --- a/src/calendar/table-date.vue +++ b/src/calendar/table-date.vue @@ -48,6 +48,7 @@ :class="getCellClasses(cell)" :title="getCellTitle(cell)" @mouseenter="handleMouseEnter(cell)" + @mouseleave="handleMouseLeave(cell)" >
{{ cell.getDate() }}
@@ -78,6 +79,12 @@ export default { prefixClass: { default: 'mx', }, + onDateMouseEnter: { + default: undefined, + }, + onDateMouseLeave: { + default: undefined, + }, }, props: { calendar: { @@ -155,7 +162,14 @@ export default { this.$emit('changepanel', panel); }, handleMouseEnter(cell) { - this.$emit('mouseenter', cell); + if (typeof this.onDateMouseEnter === 'function') { + this.onDateMouseEnter(cell); + } + }, + handleMouseLeave(cell) { + if (typeof this.onDateMouseLeave === 'function') { + this.onDateMouseLeave(cell); + } }, handleCellClick(evt) { let { target } = evt; diff --git a/src/style/index.scss b/src/style/index.scss index d2b1a79..83f0449 100644 --- a/src/style/index.scss +++ b/src/style/index.scss @@ -270,6 +270,7 @@ } .cell.not-current-month { color: #ccc; + background: none; // cover the in-range style } }