mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
feat: add calendar (#305)
* feat: add calendar * chore: update doc * chore: update * chore: update
This commit is contained in:
89
packages/calendar/__tests__/calendar.spec.ts
Normal file
89
packages/calendar/__tests__/calendar.spec.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { nextTick } from 'vue'
|
||||
import Calendar from '../src/index.vue'
|
||||
|
||||
const _mount = (template: string, data?, otherObj?) => mount({
|
||||
components: {
|
||||
'el-calendar': Calendar,
|
||||
},
|
||||
template,
|
||||
data,
|
||||
...otherObj,
|
||||
})
|
||||
|
||||
describe('Calendar.vue', () => {
|
||||
it('create', async() => {
|
||||
const wrapper = _mount(`
|
||||
<el-calendar v-model="value"></el-calendar>
|
||||
`, () => ({ value: new Date('2019-04-01') }))
|
||||
const titleEl = wrapper.find('.el-calendar__title')
|
||||
expect(/2019.*April/.test((titleEl.element as HTMLElement).innerHTML)).toBeTruthy()
|
||||
expect(wrapper.element.querySelectorAll('thead th').length).toBe(7)
|
||||
const rows = wrapper.element.querySelectorAll('.el-calendar-table__row')
|
||||
expect(rows.length).toBe(6);
|
||||
(rows[5].firstElementChild as HTMLElement).click()
|
||||
|
||||
await nextTick()
|
||||
expect(/2019.*May/.test((titleEl.element as HTMLElement).innerHTML)).toBeTruthy()
|
||||
const vm = wrapper.vm as any
|
||||
const date = vm.value
|
||||
expect(date.getFullYear()).toBe(2019)
|
||||
expect(date.getMonth()).toBe(4)
|
||||
expect((wrapper.find('.is-selected span').element as HTMLElement).innerHTML).toBe('5')
|
||||
})
|
||||
|
||||
it('range', () => {
|
||||
const wrapper = _mount(`
|
||||
<el-calendar :range="[new Date(2019, 2, 4), new Date(2019, 2, 24)]"></el-calendar>
|
||||
`)
|
||||
const titleEl = wrapper.find('.el-calendar__title')
|
||||
expect(/2019.*March/.test((titleEl.element as HTMLElement).innerHTML)).toBeTruthy()
|
||||
const rows = wrapper.element.querySelectorAll('.el-calendar-table__row')
|
||||
expect(rows.length).toBe(4)
|
||||
expect(wrapper.element.querySelector('.el-calendar__button-group')).toBeNull()
|
||||
})
|
||||
|
||||
it('range tow monthes', async() => {
|
||||
const wrapper = _mount(`
|
||||
<el-calendar :range="[new Date(2019, 3, 14), new Date(2019, 4, 18)]"></el-calendar>
|
||||
`)
|
||||
const titleEl = wrapper.find('.el-calendar__title')
|
||||
expect(/2019.*April/.test((titleEl.element as HTMLElement).innerHTML)).toBeTruthy()
|
||||
const dateTables = wrapper.element.querySelectorAll('.el-calendar-table.is-range')
|
||||
expect(dateTables.length).toBe(2)
|
||||
const rows = wrapper.element.querySelectorAll('.el-calendar-table__row')
|
||||
expect(rows.length).toBe(5)
|
||||
const cell = rows[rows.length - 1].firstElementChild;
|
||||
(cell as HTMLElement).click()
|
||||
|
||||
await nextTick()
|
||||
|
||||
expect(/2019.*May/.test((titleEl.element as HTMLElement).innerHTML)).toBeTruthy()
|
||||
expect(cell.classList.contains('is-selected')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('firstDayOfWeek', async () => {
|
||||
// default en locale, weekStart 0 Sunday
|
||||
const wrapper = _mount(`
|
||||
<el-calendar v-model="value"></el-calendar>
|
||||
`, () => ({ value: new Date('2019-04-01') }))
|
||||
const head = wrapper.element.querySelector('.el-calendar-table thead')
|
||||
expect((head.firstElementChild as HTMLElement).innerHTML).toBe('Sun')
|
||||
expect((head.lastElementChild as HTMLElement).innerHTML).toBe('Sat')
|
||||
const firstRow = wrapper.element.querySelector('.el-calendar-table__row')
|
||||
expect((firstRow.firstElementChild as HTMLElement).innerHTML).toContain('31')
|
||||
expect((firstRow.lastElementChild as HTMLElement).innerHTML).toContain('6')
|
||||
})
|
||||
|
||||
it('firstDayOfWeek in range mode', async () => {
|
||||
const wrapper = _mount(`
|
||||
<el-calendar v-model="value" :first-day-of-week="7" :range="[new Date(2019, 1, 3), new Date(2019, 2, 23)]"></el-calendar>
|
||||
`, () => ({ value: new Date('2019-03-04') }))
|
||||
const head = wrapper.element.querySelector('.el-calendar-table thead')
|
||||
expect((head.firstElementChild as HTMLElement).innerHTML).toBe('Sun')
|
||||
expect((head.lastElementChild as HTMLElement).innerHTML).toBe('Sat')
|
||||
const firstRow = wrapper.element.querySelector('.el-calendar-table__row')
|
||||
expect((firstRow.firstElementChild as HTMLElement).innerHTML).toContain('3')
|
||||
expect((firstRow.lastElementChild as HTMLElement).innerHTML).toContain('9')
|
||||
})
|
||||
})
|
||||
5
packages/calendar/index.ts
Normal file
5
packages/calendar/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { App } from 'vue'
|
||||
import Calendar from './src/index.vue'
|
||||
export default (app: App): void => {
|
||||
app.component(Calendar.name, Calendar)
|
||||
}
|
||||
12
packages/calendar/package.json
Normal file
12
packages/calendar/package.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "@element-plus/calendar",
|
||||
"version": "0.0.0",
|
||||
"main": "dist/index.js",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"vue": "^3.0.0-rc.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/test-utils": "^2.0.0-beta.3"
|
||||
}
|
||||
}
|
||||
207
packages/calendar/src/date-table.vue
Normal file
207
packages/calendar/src/date-table.vue
Normal file
@@ -0,0 +1,207 @@
|
||||
<template>
|
||||
<table
|
||||
:class="{
|
||||
'el-calendar-table': true,
|
||||
'is-range': isInRange
|
||||
}"
|
||||
cellspacing="0"
|
||||
cellpadding="0"
|
||||
>
|
||||
<thead v-if="!hideHeader">
|
||||
<th v-for="day in weekDays" :key="day">{{ day }}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="(row, index) in rows"
|
||||
:key="index"
|
||||
:class="{
|
||||
'el-calendar-table__row': true,
|
||||
'el-calendar-table__row--hide-border': index === 0 && hideHeader
|
||||
}"
|
||||
>
|
||||
<td
|
||||
v-for="(cell, key) in row"
|
||||
:key="key"
|
||||
:class="getCellClass(cell)"
|
||||
@click="pickDay(cell)"
|
||||
>
|
||||
<div class="el-calendar-day">
|
||||
<slot
|
||||
name="dateCell"
|
||||
:data="getSlotData(cell)"
|
||||
>
|
||||
<span>{{ cell.text }}</span>
|
||||
</slot>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
computed,
|
||||
defineComponent,
|
||||
ref,
|
||||
PropType,
|
||||
} from 'vue'
|
||||
import dayjs, { Dayjs } from 'dayjs'
|
||||
import localeData from 'dayjs/plugin/localeData'
|
||||
dayjs.extend(localeData)
|
||||
|
||||
const rangeArr = n => {
|
||||
return Array.from(Array(n).keys())
|
||||
}
|
||||
|
||||
export const getPrevMonthLastDays = (date: Dayjs, amount) => {
|
||||
const lastDay = date.subtract(1, 'month').endOf('month').date()
|
||||
return rangeArr(amount).map((_, index) => lastDay - (amount - index - 1))
|
||||
}
|
||||
|
||||
export const getMonthDays = (date: Dayjs) => {
|
||||
const days = date.daysInMonth()
|
||||
return rangeArr(days).map((_, index) => index + 1)
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
selectedDay: {
|
||||
type: Dayjs,
|
||||
},
|
||||
range: {
|
||||
type: Array as PropType<Array<Dayjs>>,
|
||||
},
|
||||
date: {
|
||||
type: Dayjs as PropType<Dayjs>,
|
||||
},
|
||||
hideHeader: {
|
||||
type: Boolean,
|
||||
},
|
||||
},
|
||||
emits: ['pick'],
|
||||
setup(props, ctx) {
|
||||
const WEEK_DAYS = ref(dayjs().localeData().weekdaysShort())
|
||||
|
||||
const now = dayjs()
|
||||
|
||||
// todo better way to get Day.js locale object
|
||||
const firstDayOfWeek = (now as any).$locale().weekStart || 0
|
||||
|
||||
const toNestedArr = days => {
|
||||
return rangeArr(days.length / 7).map((_, index) => {
|
||||
const start = index * 7
|
||||
return days.slice(start, start + 7)
|
||||
})
|
||||
}
|
||||
|
||||
const getFormateDate = (day, type): Dayjs => {
|
||||
let result
|
||||
if (type === 'prev') {
|
||||
result = props.date.startOf('month').subtract(1, 'month').date(day)
|
||||
} else if (type === 'next') {
|
||||
result = props.date.startOf('month').add(1, 'month').date(day)
|
||||
} else {
|
||||
result = props.date.date(day)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const getCellClass = ({ text, type }) => {
|
||||
const classes = [type]
|
||||
if (type === 'current') {
|
||||
const date_ = getFormateDate(text, type)
|
||||
if (date_.isSame(props.selectedDay, 'day')) {
|
||||
classes.push('is-selected')
|
||||
}
|
||||
if (date_.isSame(now, 'day')) {
|
||||
classes.push('is-today')
|
||||
}
|
||||
}
|
||||
return classes
|
||||
}
|
||||
|
||||
const pickDay = ({ text, type }) => {
|
||||
const date = getFormateDate(text, type)
|
||||
ctx.emit('pick', date)
|
||||
}
|
||||
|
||||
const getSlotData = ({ text, type }) => {
|
||||
const day = getFormateDate(text, type)
|
||||
return {
|
||||
isSelected: day.isSame(props.selectedDay),
|
||||
type: `${type}-month`,
|
||||
day: day.format('YYYY-MM-DD'),
|
||||
date: day.toDate(),
|
||||
}
|
||||
}
|
||||
|
||||
const isInRange = computed(() => {
|
||||
return props.range && props.range.length
|
||||
})
|
||||
|
||||
const rows = computed(() => {
|
||||
let days = []
|
||||
if (isInRange.value) {
|
||||
const [start, end] = props.range
|
||||
const currentMonthRange = rangeArr(
|
||||
end.date() - start.date() + 1,
|
||||
).map((_, index) => ({
|
||||
text: start.date() + index,
|
||||
type: 'current',
|
||||
}))
|
||||
|
||||
let remaining = currentMonthRange.length % 7
|
||||
remaining = remaining === 0 ? 0 : 7 - remaining
|
||||
const nextMonthRange = rangeArr(remaining).map((_, index) => ({
|
||||
text: index + 1,
|
||||
type: 'next',
|
||||
}))
|
||||
days = currentMonthRange.concat(nextMonthRange)
|
||||
} else {
|
||||
const firstDay = props.date.startOf('month').day() || 7
|
||||
const prevMonthDays = getPrevMonthLastDays(
|
||||
props.date,
|
||||
firstDay - firstDayOfWeek,
|
||||
).map(day => ({
|
||||
text: day,
|
||||
type: 'prev',
|
||||
}))
|
||||
const currentMonthDays = getMonthDays(props.date).map(day => ({
|
||||
text: day,
|
||||
type: 'current',
|
||||
}))
|
||||
days = [...prevMonthDays, ...currentMonthDays]
|
||||
const nextMonthDays = rangeArr(42 - days.length).map((_, index) => ({
|
||||
text: index + 1,
|
||||
type: 'next',
|
||||
}))
|
||||
days = days.concat(nextMonthDays)
|
||||
}
|
||||
return toNestedArr(days)
|
||||
})
|
||||
|
||||
const weekDays = computed(() => {
|
||||
const start = firstDayOfWeek
|
||||
|
||||
if (start === 0) {
|
||||
return WEEK_DAYS.value
|
||||
} else {
|
||||
return WEEK_DAYS.value
|
||||
.slice(start)
|
||||
.concat(WEEK_DAYS.value.slice(0, start))
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
isInRange,
|
||||
weekDays,
|
||||
rows,
|
||||
getCellClass,
|
||||
pickDay,
|
||||
getSlotData,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
</script>
|
||||
222
packages/calendar/src/index.vue
Normal file
222
packages/calendar/src/index.vue
Normal file
@@ -0,0 +1,222 @@
|
||||
<template>
|
||||
<div class="el-calendar">
|
||||
<div class="el-calendar__header">
|
||||
<div class="el-calendar__title">{{ i18nDate }}</div>
|
||||
<div v-if="validatedRange.length === 0" class="el-calendar__button-group">
|
||||
<el-button-group>
|
||||
<el-button
|
||||
size="mini"
|
||||
@click="selectDate('prev-month')"
|
||||
>
|
||||
{{ t('el.datepicker.prevMonth') }}
|
||||
</el-button>
|
||||
<el-button size="mini" @click="selectDate('today')">
|
||||
{{
|
||||
t('el.datepicker.today')
|
||||
}}
|
||||
</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
@click="selectDate('next-month')"
|
||||
>
|
||||
{{ t('el.datepicker.nextMonth') }}
|
||||
</el-button>
|
||||
</el-button-group>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="validatedRange.length === 0" class="el-calendar__body">
|
||||
<date-table
|
||||
:date="date"
|
||||
:selected-day="realSelectedDay"
|
||||
@pick="pickDay"
|
||||
>
|
||||
<template v-if="$slots.dateCell" #dateCell="data">
|
||||
<slot name="dateCell" v-bind="data"></slot>
|
||||
</template>
|
||||
</date-table>
|
||||
</div>
|
||||
<div v-else class="el-calendar__body">
|
||||
<date-table
|
||||
v-for="(range_, index) in validatedRange"
|
||||
:key="index"
|
||||
:date="range_[0]"
|
||||
:selected-day="realSelectedDay"
|
||||
:range="range_"
|
||||
:hide-header="index !== 0"
|
||||
@pick="pickDay"
|
||||
>
|
||||
<template v-if="$slots.dateCell" #dateCell="data">
|
||||
<slot name="dateCell" v-bind="data"></slot>
|
||||
</template>
|
||||
</date-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { t } from '@element-plus/locale'
|
||||
import ElButton from '@element-plus/button/src/button.vue'
|
||||
import ElButtonGroup from '@element-plus/button/src/button-group.vue'
|
||||
import DateTable from './date-table.vue'
|
||||
import {
|
||||
ref,
|
||||
ComputedRef,
|
||||
PropType,
|
||||
computed,
|
||||
defineComponent,
|
||||
} from 'vue'
|
||||
import dayjs, { Dayjs } from 'dayjs'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ElCalendar',
|
||||
|
||||
components: {
|
||||
DateTable,
|
||||
ElButton,
|
||||
ElButtonGroup,
|
||||
},
|
||||
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Date,
|
||||
},
|
||||
range: {
|
||||
type: Array as PropType<Array<Date>>,
|
||||
validator: (range: Date): boolean => {
|
||||
if (Array.isArray(range)) {
|
||||
return (
|
||||
range.length === 2 &&
|
||||
range.every(
|
||||
item => item instanceof Date,
|
||||
)
|
||||
)
|
||||
}
|
||||
return false
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
emits: ['input', 'update:modelValue'],
|
||||
setup(props, ctx) {
|
||||
const selectedDay = ref(null)
|
||||
const now = dayjs()
|
||||
|
||||
const prevMonthDayjs = computed(() => {
|
||||
return date.value.subtract(1, 'month')
|
||||
})
|
||||
const curMonthDatePrefix = computed(() => {
|
||||
return dayjs(date.value).format('YYYY-MM')
|
||||
})
|
||||
|
||||
const nextMonthDayjs = computed(() => {
|
||||
return date.value.add(1, 'month')
|
||||
})
|
||||
|
||||
const i18nDate = computed(() => {
|
||||
const pickedMonth = `el.datepicker.month${date.value.format('M')}`
|
||||
return `${date.value.year()} ${t('el.datepicker.year')} ${t(pickedMonth)}`
|
||||
})
|
||||
|
||||
const realSelectedDay = computed({
|
||||
get() {
|
||||
if (!props.modelValue) return selectedDay.value
|
||||
return date.value
|
||||
},
|
||||
set(val: Dayjs) {
|
||||
selectedDay.value = val
|
||||
const result = val.toDate()
|
||||
|
||||
ctx.emit('input', result)
|
||||
ctx.emit('update:modelValue', result)
|
||||
},
|
||||
})
|
||||
|
||||
const date: ComputedRef<Dayjs> = computed(() => {
|
||||
if (!props.modelValue) {
|
||||
if (realSelectedDay.value) {
|
||||
return realSelectedDay.value
|
||||
} else if (validatedRange.value.length) {
|
||||
return validatedRange.value[0][0]
|
||||
}
|
||||
return now
|
||||
} else {
|
||||
return dayjs(props.modelValue)
|
||||
}
|
||||
})
|
||||
|
||||
// if range is valid, we get a two-digit array
|
||||
const validatedRange = computed(() => {
|
||||
if (!props.range) return []
|
||||
const rangeArrDayjs = props.range.map(_ => dayjs(_))
|
||||
const [startDayjs, endDayjs] = rangeArrDayjs
|
||||
if (startDayjs.isAfter(endDayjs)) {
|
||||
console.warn(
|
||||
'[ElementCalendar]end time should be greater than start time',
|
||||
)
|
||||
return []
|
||||
}
|
||||
if (startDayjs.isSame(endDayjs, 'month')) {
|
||||
// same month
|
||||
return [[
|
||||
startDayjs.startOf('week'),
|
||||
endDayjs.endOf('week'),
|
||||
]]
|
||||
} else {
|
||||
// two months
|
||||
if (startDayjs.add(1, 'month').month() !== endDayjs.month()) {
|
||||
console.warn(
|
||||
'[ElementCalendar]start time and end time interval must not exceed two months',
|
||||
)
|
||||
return []
|
||||
}
|
||||
const endMonthFirstDay = endDayjs.startOf('month')
|
||||
const endMonthFirstWeekDay = endMonthFirstDay.startOf('week')
|
||||
let endMonthStart = endMonthFirstDay
|
||||
if (!endMonthFirstDay.isSame(endMonthFirstWeekDay, 'month')) {
|
||||
endMonthStart = endMonthFirstDay.endOf('week').add(1, 'day')
|
||||
}
|
||||
return [
|
||||
[
|
||||
startDayjs.startOf('week'),
|
||||
startDayjs.endOf('month'),
|
||||
],
|
||||
[
|
||||
endMonthStart,
|
||||
endDayjs.endOf('week'),
|
||||
],
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const pickDay = (day: Dayjs) => {
|
||||
realSelectedDay.value = day
|
||||
}
|
||||
|
||||
const selectDate = type => {
|
||||
let day: Dayjs
|
||||
if (type === 'prev-month') {
|
||||
day = prevMonthDayjs.value
|
||||
} else if (type === 'next-month') {
|
||||
day = nextMonthDayjs.value
|
||||
} else {
|
||||
day = now
|
||||
}
|
||||
|
||||
if (day.isSame(date.value, 'day')) return
|
||||
pickDay(day)
|
||||
}
|
||||
|
||||
return {
|
||||
selectedDay,
|
||||
curMonthDatePrefix,
|
||||
i18nDate,
|
||||
realSelectedDay,
|
||||
date,
|
||||
validatedRange,
|
||||
pickDay,
|
||||
selectDate,
|
||||
t,
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
@@ -34,8 +34,10 @@ import ElSlider from '@element-plus/slider'
|
||||
import ElInput from '@element-plus/input'
|
||||
import ElTransfer from '@element-plus/transfer'
|
||||
import ElDialog from '@element-plus/dialog'
|
||||
import ElCalendar from '@element-plus/calendar'
|
||||
import ElInfiniteScroll from '@element-plus/infinite-scroll'
|
||||
|
||||
|
||||
export {
|
||||
ElAlert,
|
||||
ElAvatar,
|
||||
@@ -71,6 +73,7 @@ export {
|
||||
ElInput,
|
||||
ElTransfer,
|
||||
ElDialog,
|
||||
ElCalendar,
|
||||
ElInfiniteScroll,
|
||||
}
|
||||
|
||||
@@ -110,6 +113,7 @@ const install = (app: App): void => {
|
||||
ElInput(app)
|
||||
ElTransfer(app)
|
||||
ElDialog(app)
|
||||
ElCalendar(app)
|
||||
ElInfiniteScroll(app)
|
||||
}
|
||||
|
||||
|
||||
@@ -93,18 +93,20 @@
|
||||
{{ displayedLang }}
|
||||
<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</span>
|
||||
<el-dropdown-menu
|
||||
class="nav-dropdown-list"
|
||||
@input="handleLangDropdownToggle"
|
||||
>
|
||||
<el-dropdown-item
|
||||
v-for="(value, key) in langs"
|
||||
:key="key"
|
||||
@click="switchLang(key)"
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu
|
||||
class="nav-dropdown-list"
|
||||
@input="handleLangDropdownToggle"
|
||||
>
|
||||
{{ value }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
v-for="(value, key) in langs"
|
||||
:key="key"
|
||||
@click="switchLang(key)"
|
||||
>
|
||||
{{ value }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -26,12 +26,11 @@ Display date.
|
||||
:::demo Customize what is displayed in the calendar cell by setting `scoped-slot` named `dateCell`. In `scoped-slot` you can get the date (the date of the current cell), data (including the type, isSelected, day attribute). For details, please refer to the API documentation below.
|
||||
```html
|
||||
<el-calendar>
|
||||
<!-- Use 2.5 slot syntax. If you use Vue 2.6, please use new slot syntax-->
|
||||
<template
|
||||
slot="dateCell"
|
||||
slot-scope="{date, data}">
|
||||
#dateCell="{data}"
|
||||
>
|
||||
<p :class="data.isSelected ? 'is-selected' : ''">
|
||||
{{ data.day.split('-').slice(1).join('-') }} {{ data.isSelected ? '✔️' : ''}}
|
||||
{{ data.day.split('-').slice(1).join('-') }} {{ data.isSelected ? '✔️' : '' }}
|
||||
</p>
|
||||
</template>
|
||||
</el-calendar>
|
||||
@@ -47,7 +46,7 @@ Display date.
|
||||
|
||||
:::demo Set the `range` attribute to specify the display range of the calendar. Start time must be Monday, end time must be Sunday, and the time span cannot exceed two months.
|
||||
```html
|
||||
<el-calendar :range="['2019-03-04', '2019-03-24']">
|
||||
<el-calendar :range="[new Date(2019, 2, 4), new Date(2019, 2, 24)]">
|
||||
</el-calendar>
|
||||
```
|
||||
:::
|
||||
|
||||
@@ -27,12 +27,11 @@ Muestra fechas.
|
||||
|
||||
```html
|
||||
<el-calendar>
|
||||
<!-- Use 2.5 slot syntax. If you use Vue 2.6, please use new slot syntax-->
|
||||
<template
|
||||
slot="dateCell"
|
||||
slot-scope="{date, data}">
|
||||
#dateCell="{data}"
|
||||
>
|
||||
<p :class="data.isSelected ? 'is-selected' : ''">
|
||||
{{ data.day.split('-').slice(1).join('-') }} {{ data.isSelected ? '✔️' : ''}}
|
||||
{{ data.day.split('-').slice(1).join('-') }} {{ data.isSelected ? '✔️' : '' }}
|
||||
</p>
|
||||
</template>
|
||||
</el-calendar>
|
||||
@@ -48,7 +47,7 @@ Muestra fechas.
|
||||
|
||||
:::demo Defina el atributo `range` para especificar el rango de visualización del calendario. El tiempo de inicio debe ser el lunes, el tiempo de finalización debe ser el domingo y el período no puede exceder los dos meses.
|
||||
```html
|
||||
<el-calendar :range="['2019-03-04', '2019-03-24']">
|
||||
<el-calendar :range="[new Date(2019, 2, 4), new Date(2019, 2, 24)]">
|
||||
</el-calendar>
|
||||
```
|
||||
:::
|
||||
|
||||
@@ -26,12 +26,11 @@ Affiche un calendrier.
|
||||
:::demo Personnalisez le contenu du calendrier en utilisant le `scoped-slot` appelé `dateCell`. Dans ce `scoped-slot` vous aurez accès au paramètres date (date de la cellule courante), data (incluant les attributs type, isSelected et day). Pour plus d'informations, référez-vous à la documentation ci-dessous.
|
||||
```html
|
||||
<el-calendar>
|
||||
<!-- Use 2.5 slot syntax. If you use Vue 2.6, please use new slot syntax-->
|
||||
<template
|
||||
slot="dateCell"
|
||||
slot-scope="{date, data}">
|
||||
#dateCell="{data}"
|
||||
>
|
||||
<p :class="data.isSelected ? 'is-selected' : ''">
|
||||
{{ data.day.split('-').slice(1).join('-') }} {{ data.isSelected ? '✔️' : ''}}
|
||||
{{ data.day.split('-').slice(1).join('-') }} {{ data.isSelected ? '✔️' : '' }}
|
||||
</p>
|
||||
</template>
|
||||
</el-calendar>
|
||||
@@ -47,7 +46,7 @@ Affiche un calendrier.
|
||||
|
||||
:::demo Utilisez l'attribut `range` pour afficher un intervalle particulier. Le début doit être un lundi et la fin un dimanche, l'intervalle ne pouvant excéder deux mois.
|
||||
```html
|
||||
<el-calendar :range="['2019-03-04', '2019-03-24']">
|
||||
<el-calendar :range="[new Date(2019, 2, 4), new Date(2019, 2, 24)]">
|
||||
</el-calendar>
|
||||
```
|
||||
:::
|
||||
|
||||
@@ -26,12 +26,11 @@
|
||||
:::demo 通过设置名为 `dateCell` 的 `scoped-slot` 来自定义日历单元格中显示的内容。在 `scoped-slot` 可以获取到 date(当前单元格的日期), data(包括 type,isSelected,day 属性)。详情解释参考下方的 API 文档。
|
||||
```html
|
||||
<el-calendar>
|
||||
<!-- 这里使用的是 2.5 slot 语法,对于新项目请使用 2.6 slot 语法-->
|
||||
<template
|
||||
slot="dateCell"
|
||||
slot-scope="{date, data}">
|
||||
#dateCell="{data}"
|
||||
>
|
||||
<p :class="data.isSelected ? 'is-selected' : ''">
|
||||
{{ data.day.split('-').slice(1).join('-') }} {{ data.isSelected ? '✔️' : ''}}
|
||||
{{ data.day.split('-').slice(1).join('-') }} {{ data.isSelected ? '✔️' : '' }}
|
||||
</p>
|
||||
</template>
|
||||
</el-calendar>
|
||||
@@ -47,7 +46,7 @@
|
||||
|
||||
:::demo 设置 `range` 属性指定日历的显示范围。开始时间必须是周起始日,结束时间必须是周结束日,且时间跨度不能超过两个月。
|
||||
```html
|
||||
<el-calendar :range="['2019-03-04', '2019-03-24']">
|
||||
<el-calendar :range="[new Date(2019, 2, 4), new Date(2019, 2, 24)]">
|
||||
</el-calendar>
|
||||
```
|
||||
:::
|
||||
|
||||
@@ -12,6 +12,9 @@ import './demo-styles/index.scss'
|
||||
import './assets/styles/common.css'
|
||||
import './assets/styles/fonts/style.css'
|
||||
import icon from './icon.json'
|
||||
import dayjs from 'dayjs'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
dayjs.locale('zh-cn') // todo: locale based on Doc site lang
|
||||
|
||||
import App from './app.vue'
|
||||
import ElementPlus from 'element-plus'
|
||||
|
||||
Reference in New Issue
Block a user