diff --git a/components.js b/components.js
index e0ee8e4be..d601c0a41 100644
--- a/components.js
+++ b/components.js
@@ -46,4 +46,5 @@ module.exports = [
'picker',
'dialog',
'toast',
+ 'calendar',
];
diff --git a/docs/markdown/changelog-v3.zh-CN.md b/docs/markdown/changelog-v3.zh-CN.md
index 8e5705bcf..168a06737 100644
--- a/docs/markdown/changelog-v3.zh-CN.md
+++ b/docs/markdown/changelog-v3.zh-CN.md
@@ -24,16 +24,17 @@ Vant 遵循 [Semver](https://semver.org/lang/zh-CN/) 语义化版本规范。
以下改动是为了适配 Vue 3 的 v-model API 用法变更:
-- Tabs: `v-model` 重命名为 `v-model:active`
-- Popup: `v-model` 重命名为 `v-model:show`
+- ActionSheet: `v-model` 重命名为 `v-model:show`
+- Calendar: `v-model` 重命名为 `v-model:show`
- Circle: `v-model` 重命名为 `v-model:currentRate`
- Dialog: `v-model` 重命名为 `v-model:show`
-- ShareSheet: `v-model` 重命名为 `v-model:show`
-- ActionSheet: `v-model` 重命名为 `v-model:show`
-- List: `v-model` 重命名为 `v-model:loading`,`error.sync` 重命名为 `v-model:error`
- Field: v-model 对应的属性 `value` 重命名为 `modelValue`,事件由 `input` 重命名为 `update:modelValue`
-- Switch: v-model 对应的属性 `value` 重命名为 `modelValue`,事件由 `input` 重命名为 `update:modelValue`
+- List: `v-model` 重命名为 `v-model:loading`,`error.sync` 重命名为 `v-model:error`
+- Popup: `v-model` 重命名为 `v-model:show`
- Sidebar: v-model 对应的属性 `activeKey` 重命名为 `modelValue`,事件由 `input` 重命名为 `update:modelValue`
+- ShareSheet: `v-model` 重命名为 `v-model:show`
+- Switch: v-model 对应的属性 `value` 重命名为 `modelValue`,事件由 `input` 重命名为 `update:modelValue`
+- Tabs: `v-model` 重命名为 `v-model:active`
- TreeSelect: `active-id.sync` 重命名为 `v-model:active-id`
- TreeSelect: `main-active-index.sync` 重命名为 `v-model:main-active-index`
diff --git a/src/calendar/README.md b/src/calendar/README.md
index 69c0d53e7..8184de2f4 100644
--- a/src/calendar/README.md
+++ b/src/calendar/README.md
@@ -21,7 +21,7 @@ The `confirm` event will be triggered after the date selection is completed.
```html
-
+
```
```js
@@ -48,7 +48,7 @@ export default {
```html
-
+
```
```js
@@ -74,7 +74,7 @@ You can select a date range after setting `type` to`range`. In range mode, the d
```html
-
+
```
```js
@@ -103,7 +103,7 @@ export default {
Set `show-confirm` to `false` to hide the confirm button. In this case, the `confirm` event will be triggered immediately after the selection is completed.
```html
-
+
```
### Custom Color
@@ -111,7 +111,7 @@ Set `show-confirm` to `false` to hide the confirm button. In this case, the `con
Use `color` prop to custom calendar color.
```html
-
+
```
### Custom Date Range
@@ -119,7 +119,7 @@ Use `color` prop to custom calendar color.
Use `min-date` and `max-date` to custom date range.
```html
-
+
```
```js
@@ -140,7 +140,7 @@ Use `confirm-text` and `confirm-disabled-text` to custom confirm text.
```html
+
```
```js
@@ -189,7 +189,7 @@ export default {
Use `position` to custom popup position,can be set to `top`、`left`、`right`.
```html
-
+
```
### Max Range
@@ -251,7 +251,7 @@ Following props are supported when the poppable is true
| Attribute | Description | Type | Default |
| --- | --- | --- | --- |
-| v-model | Whether to show calendar | _boolean_ | `false` |
+| v-model:show | Whether to show calendar | _boolean_ | `false` |
| position | Popup position, can be set to `top` `right` `left` | _string_ | `bottom` |
| round | Whether to show round corner | _boolean_ | `true` |
| close-on-popstate `v2.4.4` | Whether to close when popstate | _boolean_ | `true` |
diff --git a/src/calendar/README.zh-CN.md b/src/calendar/README.zh-CN.md
index 075b38fa9..adfbca1fe 100644
--- a/src/calendar/README.zh-CN.md
+++ b/src/calendar/README.zh-CN.md
@@ -21,7 +21,7 @@ Vue.use(Calendar);
```html
-
+
```
```js
@@ -50,7 +50,7 @@ export default {
```html
-
+
```
```js
@@ -76,7 +76,7 @@ export default {
```html
-
+
```
```js
@@ -105,7 +105,7 @@ export default {
将 `show-confirm` 设置为 `false` 可以隐藏确认按钮,这种情况下选择完成后会立即触发 `confirm` 事件。
```html
-
+
```
### 自定义颜色
@@ -113,7 +113,7 @@ export default {
通过 `color` 属性可以自定义日历的颜色,对选中日期和底部按钮生效。
```html
-
+
```
### 自定义日期范围
@@ -121,7 +121,7 @@ export default {
通过 `min-date` 和 `max-date` 定义日历的范围。
```html
-
+
```
```js
@@ -142,7 +142,7 @@ export default {
```html
+
```
```js
@@ -191,7 +191,7 @@ export default {
通过 `position` 属性自定义弹出层的弹出位置,可选值为 `top`、`left`、`right`。
```html
-
+
```
### 日期区间最大范围
@@ -253,7 +253,7 @@ export default {
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
-| v-model | 是否显示日历弹窗 | _boolean_ | `false` |
+| v-model:show | 是否显示日历弹窗 | _boolean_ | `false` |
| position | 弹出位置,可选值为 `top` `right` `left` | _string_ | `bottom` |
| round | 是否显示圆角弹窗 | _boolean_ | `true` |
| close-on-popstate `v2.4.4` | 是否在页面回退时自动关闭 | _boolean_ | `true` |
diff --git a/src/calendar/components/Header.js b/src/calendar/components/Header.js
index 814583b29..9166999b6 100644
--- a/src/calendar/components/Header.js
+++ b/src/calendar/components/Header.js
@@ -15,7 +15,7 @@ export default createComponent({
methods: {
genTitle() {
if (this.showTitle) {
- const title = this.slots('title') || this.title || t('title');
+ const title = this.$slots.title?.() || this.title || t('title');
return
;
}
},
diff --git a/src/calendar/components/Month.js b/src/calendar/components/Month.js
index a04dfda3e..dd4fee992 100644
--- a/src/calendar/components/Month.js
+++ b/src/calendar/components/Month.js
@@ -31,6 +31,8 @@ export default createComponent({
firstDayOfWeek: Number,
},
+ emits: ['click'],
+
data() {
return {
visible: false,
@@ -183,18 +185,16 @@ export default createComponent({
return 'disabled';
}
- if (type === 'single') {
+ if (Array.isArray(currentDate)) {
+ if (type === 'multiple') {
+ return this.getMultipleDayType(day);
+ }
+ if (type === 'range') {
+ return this.getRangeDayType(day);
+ }
+ } else if (type === 'single') {
return compareDay(day, currentDate) === 0 ? 'selected' : '';
}
-
- if (type === 'multiple') {
- return this.getMultipleDayType(day);
- }
-
- /* istanbul ignore else */
- if (type === 'range') {
- return this.getRangeDayType(day);
- }
},
getBottomInfo(type) {
diff --git a/src/calendar/demo/index.vue b/src/calendar/demo/index.vue
index 5b2c7a767..1dfb3476c 100644
--- a/src/calendar/demo/index.vue
+++ b/src/calendar/demo/index.vue
@@ -102,7 +102,7 @@
{
if (compareMonth(month, targetDate) === 0) {
- const { body, months } = this.$refs;
- months[index].scrollIntoView(body);
+ const { body } = this.$refs;
+ this.monthRefs[index].scrollIntoView(body);
return true;
}
@@ -244,9 +257,10 @@ export default createComponent({
// calculate the position of the elements
// and find the elements that needs to be rendered
onScroll() {
- const { body, months } = this.$refs;
+ const { body } = this.$refs;
+ const { months, monthRefs } = this;
const top = getScrollTop(body);
- const heights = months.map((item) => item.getHeight());
+ const heights = months.map((item, index) => monthRefs[index].getHeight());
const heightSum = heights.reduce((a, b) => a + b, 0);
// iOS scroll bounce may exceed the range
@@ -262,17 +276,17 @@ export default createComponent({
const visible = height <= bottom && height + heights[i] >= top;
if (visible && !currentMonth) {
- currentMonth = months[i];
+ currentMonth = monthRefs[i];
}
- if (!months[i].visible && visible) {
+ if (!monthRefs[i].visible && visible) {
this.$emit('month-show', {
- date: months[i].date,
- title: months[i].title,
+ date: monthRefs[i].date,
+ title: monthRefs[i].title,
});
}
- months[i].visible = visible;
+ monthRefs[i].visible = visible;
height += heights[i];
}
@@ -327,7 +341,7 @@ export default createComponent({
},
togglePopup(val) {
- this.$emit('input', val);
+ this.$emit('update:show', val);
},
select(date, complete) {
@@ -376,8 +390,9 @@ export default createComponent({
const showMonthTitle = index !== 0 || !this.showSubtitle;
return (
{
+ this.monthRefs[index] = val;
+ }}
date={date}
type={this.type}
color={this.color}
@@ -398,10 +413,8 @@ export default createComponent({
},
genFooterContent() {
- const slot = this.slots('footer');
-
- if (slot) {
- return slot;
+ if (this.$slots.footer) {
+ return this.$slots.footer();
}
if (this.showConfirm) {
@@ -438,13 +451,13 @@ export default createComponent({
return (
this.slots('title'),
- }}
firstDayOfWeek={this.dayOffset}
/>
@@ -459,23 +472,25 @@ export default createComponent({
render() {
if (this.poppable) {
const createListener = (name) => () => this.$emit(name);
+ const listeners = {
+ 'onUpdate:show': this.togglePopup,
+ onOpen: createListener('open'),
+ onClose: createListener('close'),
+ onOpened: createListener('opened'),
+ onClosed: createListener('closed'),
+ };
return (
diff --git a/vant.config.js b/vant.config.js
index b687d8194..ac3fe0f12 100644
--- a/vant.config.js
+++ b/vant.config.js
@@ -115,10 +115,10 @@ module.exports = {
{
title: '表单组件',
items: [
- // {
- // path: 'calendar',
- // title: 'Calendar 日历',
- // },
+ {
+ path: 'calendar',
+ title: 'Calendar 日历',
+ },
// {
// path: 'checkbox',
// title: 'Checkbox 复选框',
@@ -449,10 +449,10 @@ module.exports = {
{
title: 'Form Components',
items: [
- // {
- // path: 'calendar',
- // title: 'Calendar',
- // },
+ {
+ path: 'calendar',
+ title: 'Calendar',
+ },
// {
// path: 'checkbox',
// title: 'Checkbox',