diff --git a/src/calendar/components/Header.js b/src/calendar/components/Header.js
index 9166999b6..e4fdf2fc5 100644
--- a/src/calendar/components/Header.js
+++ b/src/calendar/components/Header.js
@@ -12,25 +12,24 @@ export default createComponent({
firstDayOfWeek: Number,
},
- methods: {
- genTitle() {
- if (this.showTitle) {
- const title = this.$slots.title?.() || this.title || t('title');
+ setup(props, { slots }) {
+ const renderTitle = () => {
+ if (props.showTitle) {
+ const text = props.title || t('title');
+ const title = slots.title ? slots.title : text;
return
;
}
- },
+ };
- genSubtitle() {
- if (this.showSubtitle) {
- return ;
+ const renderSubtitle = () => {
+ if (props.showSubtitle) {
+ return ;
}
- },
+ };
- genWeekDays() {
+ const renderWeekDays = () => {
+ const { firstDayOfWeek } = props;
const weekdays = t('weekdays');
-
- const { firstDayOfWeek } = this;
-
const renderWeekDays = [
...weekdays.slice(firstDayOfWeek, 7),
...weekdays.slice(0, firstDayOfWeek),
@@ -38,20 +37,18 @@ export default createComponent({
return (
- {renderWeekDays.map((item) => (
- {item}
+ {renderWeekDays.map((text) => (
+ {text}
))}
);
- },
- },
+ };
- render() {
- return (
+ return () => (
);
},
diff --git a/src/calendar/components/Month.js b/src/calendar/components/Month.js
index 67ee4ec74..eff781bbc 100644
--- a/src/calendar/components/Month.js
+++ b/src/calendar/components/Month.js
@@ -1,4 +1,6 @@
+import { ref, computed } from 'vue';
import { createNamespace, addUnit } from '../../utils';
+import { unitToPx } from '../../utils/format/unit';
import { setScrollTop } from '../../utils/dom/scroll';
import {
t,
@@ -33,92 +35,62 @@ export default createComponent({
emits: ['click'],
- data() {
- return {
- visible: false,
- };
- },
+ setup(props, { emit }) {
+ const visible = ref(false);
+ const daysRef = ref(null);
+ const monthRef = ref(null);
- computed: {
- title() {
- return formatMonthTitle(this.date);
- },
+ const title = computed(() => formatMonthTitle(props.date));
- rowHeightWithUnit() {
- if (this.rowHeight !== ROW_HEIGHT) {
- return addUnit(this.rowHeight);
+ const rowHeight = computed(() => {
+ if (props.rowHeight !== ROW_HEIGHT) {
+ return addUnit(props.rowHeight);
}
- },
+ });
- offset() {
- const { firstDayOfWeek } = this;
+ const offset = computed(() => {
+ const realDay = props.date.getDay();
- const realDay = this.date.getDay();
-
- if (!firstDayOfWeek) {
- return realDay;
+ if (props.firstDayOfWeek) {
+ return (realDay + 7 - props.firstDayOfWeek) % 7;
}
+ return realDay;
+ });
- return (realDay + 7 - this.firstDayOfWeek) % 7;
- },
+ const totalDay = computed(() =>
+ getMonthEndDay(props.date.getFullYear(), props.date.getMonth() + 1)
+ );
- totalDay() {
- return getMonthEndDay(this.date.getFullYear(), this.date.getMonth() + 1);
- },
-
- shouldRender() {
- return this.visible || !this.lazyRender;
- },
-
- monthStyle() {
- if (!this.shouldRender) {
- const padding =
- Math.ceil((this.totalDay + this.offset) / 7) * this.rowHeight;
+ const shouldRender = computed(() => visible.value || !props.lazyRender);
+ const monthStyle = computed(() => {
+ if (!shouldRender.value) {
+ const rowCount = Math.ceil((totalDay.value + offset.value) / 7);
+ const padding = rowCount * unitToPx(props.rowHeight);
return {
paddingBottom: `${padding}px`,
};
}
- },
+ });
- days() {
- const days = [];
- const year = this.date.getFullYear();
- const month = this.date.getMonth();
-
- for (let day = 1; day <= this.totalDay; day++) {
- const date = new Date(year, month, day);
- const type = this.getDayType(date);
-
- let config = {
- date,
- type,
- text: day,
- bottomInfo: this.getBottomInfo(type),
- };
-
- if (this.formatter) {
- config = this.formatter(config);
- }
-
- days.push(config);
+ let height;
+ const getHeight = () => {
+ if (!height) {
+ ({ height } = monthRef.value.getBoundingClientRect());
}
+ return height;
+ };
- return days;
- },
- },
+ const setVisible = (value) => {
+ visible.value = value;
+ };
- methods: {
- getHeight() {
- if (!this.height) {
- this.height = this.$el.getBoundingClientRect().height;
- }
- return this.height;
- },
+ const getDate = () => props.data;
- scrollIntoView(body) {
- const { days, month } = this.$refs;
- const el = this.showSubtitle ? days : month;
+ const getTitle = () => title.value;
+
+ const scrollIntoView = (body) => {
+ const el = props.showSubtitle ? daysRef.value : monthRef.value;
const scrollTop =
el.getBoundingClientRect().top -
@@ -126,11 +98,11 @@ export default createComponent({
body.scrollTop;
setScrollTop(body, scrollTop);
- },
+ };
- getMultipleDayType(day) {
+ const getMultipleDayType = (day) => {
const isSelected = (date) =>
- this.currentDate.some((item) => compareDay(item, date) === 0);
+ props.currentDate.some((item) => compareDay(item, date) === 0);
if (isSelected(day)) {
const prevDay = getPrevDay(day);
@@ -141,19 +113,20 @@ export default createComponent({
if (prevSelected && nextSelected) {
return 'multiple-middle';
}
-
if (prevSelected) {
return 'end';
}
-
- return nextSelected ? 'start' : 'multiple-selected';
+ if (nextSelected) {
+ return 'start';
+ }
+ return 'multiple-selected';
}
return '';
- },
+ };
- getRangeDayType(day) {
- const [startDay, endDay] = this.currentDate;
+ const getRangeDayType = (day) => {
+ const [startDay, endDay] = props.currentDate;
if (!startDay) {
return '';
@@ -167,25 +140,22 @@ export default createComponent({
const compareToEnd = compareDay(day, endDay);
- if (compareToStart === 0 && compareToEnd === 0 && this.allowSameDay) {
+ if (compareToStart === 0 && compareToEnd === 0 && props.allowSameDay) {
return 'start-end';
}
-
if (compareToStart === 0) {
return 'start';
}
-
if (compareToEnd === 0) {
return 'end';
}
-
if (compareToStart > 0 && compareToEnd < 0) {
return 'middle';
}
- },
+ };
- getDayType(day) {
- const { type, minDate, maxDate, currentDate } = this;
+ const getDayType = (day) => {
+ const { type, minDate, maxDate, currentDate } = props;
if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
return 'disabled';
@@ -193,18 +163,18 @@ export default createComponent({
if (Array.isArray(currentDate)) {
if (type === 'multiple') {
- return this.getMultipleDayType(day);
+ return getMultipleDayType(day);
}
if (type === 'range') {
- return this.getRangeDayType(day);
+ return getRangeDayType(day);
}
} else if (type === 'single') {
return compareDay(day, currentDate) === 0 ? 'selected' : '';
}
- },
+ };
- getBottomInfo(type) {
- if (this.type === 'range') {
+ const getBottomInfo = (type) => {
+ if (props.type === 'range') {
if (type === 'start' || type === 'end') {
return t(type);
}
@@ -212,18 +182,19 @@ export default createComponent({
return t('startEnd');
}
}
- },
+ };
- getDayStyle(type, index) {
+ const getDayStyle = (type, index) => {
+ const { color } = props;
const style = {
- height: this.rowHeightWithUnit,
+ height: rowHeight.value,
};
if (index === 0) {
- style.marginLeft = `${(100 * this.offset) / 7}%`;
+ style.marginLeft = `${(100 * offset.value) / 7}%`;
}
- if (this.color) {
+ if (color) {
if (
type === 'start' ||
type === 'end' ||
@@ -231,48 +202,35 @@ export default createComponent({
type === 'multiple-selected' ||
type === 'multiple-middle'
) {
- style.background = this.color;
+ style.background = color;
} else if (type === 'middle') {
- style.color = this.color;
+ style.color = color;
}
}
return style;
- },
+ };
- genTitle() {
- if (this.showMonthTitle) {
- return {this.title}
;
+ const renderTitle = () => {
+ if (props.showMonthTitle) {
+ return {title.value}
;
}
- },
+ };
- genMark() {
- if (this.showMark) {
- return {this.date.getMonth() + 1}
;
+ const renderMark = () => {
+ if (props.showMark) {
+ return {props.date.getMonth() + 1}
;
}
- },
+ };
- genDays() {
- if (this.shouldRender) {
- return (
-
- {this.genMark()}
- {this.days.map(this.genDay)}
-
- );
- }
-
- return ;
- },
-
- genDay(item, index) {
+ const renderDay = (item, index) => {
const { type, topInfo, bottomInfo } = item;
- const style = this.getDayStyle(type, index);
+ const style = getDayStyle(type, index);
const disabled = type === 'disabled';
const onClick = () => {
if (!disabled) {
- this.$emit('click', item);
+ emit('click', item);
}
};
@@ -294,9 +252,9 @@ export default createComponent({
{TopInfo}
@@ -320,15 +278,60 @@ export default createComponent({
{BottomInfo}
);
- },
- },
+ };
- render() {
- return (
-
- {this.genTitle()}
- {this.genDays()}
-
- );
+ const days = computed(() => {
+ const days = [];
+ const year = props.date.getFullYear();
+ const month = props.date.getMonth();
+
+ for (let day = 1; day <= totalDay.value; day++) {
+ const date = new Date(year, month, day);
+ const type = getDayType(date);
+
+ let config = {
+ date,
+ type,
+ text: day,
+ bottomInfo: getBottomInfo(type),
+ };
+
+ if (props.formatter) {
+ config = props.formatter(config);
+ }
+
+ days.push(config);
+ }
+
+ return days;
+ });
+
+ const renderDays = () => {
+ if (shouldRender.value) {
+ return (
+
+ {renderMark()}
+ {days.value.map(renderDay)}
+
+ );
+ }
+
+ return ;
+ };
+
+ return (vm) => {
+ vm.getDate = getDate;
+ vm.getTitle = getTitle;
+ vm.getHeight = getHeight;
+ vm.setVisible = setVisible;
+ vm.scrollIntoView = scrollIntoView;
+
+ return (
+
+ {renderTitle()}
+ {renderDays()}
+
+ );
+ };
},
});
diff --git a/src/calendar/index.js b/src/calendar/index.js
index d869fde53..d2f97caaa 100644
--- a/src/calendar/index.js
+++ b/src/calendar/index.js
@@ -288,18 +288,18 @@ export default createComponent({
if (!monthRefs[i].visible && visible) {
this.$emit('month-show', {
- date: monthRefs[i].date,
- title: monthRefs[i].title,
+ date: monthRefs[i].getDate(),
+ title: monthRefs[i].getTitle(),
});
}
- monthRefs[i].visible = visible;
+ monthRefs[i].setVisible(visible);
height += heights[i];
}
/* istanbul ignore else */
if (currentMonth) {
- this.subtitle = currentMonth.title;
+ this.subtitle = currentMonth.getTitle();
}
},