概述
<b-calendar>
符合 WAI-ARIA 可访问性,针对键盘控制(箭头、向上/向下翻页、主页和结束键)进行了优化。还支持国际化,如果未指定语言环境,则默认为浏览器的语言环境或页面的语言环境。
如果您需要一个日期选择器作为自定义表单控件输入,请使用 <b-form-datepicker>
组件。
<template>
<b-row>
<b-col md="auto">
<b-calendar v-model="value" @context="onContext" locale="en-US"></b-calendar>
</b-col>
<b-col>
<p>Value: <b>'{{ value }}'</b></p>
<p class="mb-0">Context:</p>
<pre class="small">{{ context }}</pre>
</b-col>
</b-row>
</template>
<script>
export default {
data() {
return {
value: '',
context: null
}
},
methods: {
onContext(ctx) {
this.context = ctx
}
}
}
</script>
v-model
返回值
默认情况下,<b-calendar>
以 YYYY-MM-DD
格式的字符串返回日期,这与原生浏览器 <input type="date">
控件返回的格式相同。你可以通过设置 value-as-date
属性,让 <b-calendar>
返回一个 Date
对象(不含时间部分)作为 v-model
值。
如果没有选择日期,<b-calendar>
会返回一个空字符串 ''
,或者如果设置了 value-as-date
属性,则返回 null
。
请注意,当设置 value-as-date
属性时,返回的 Date
对象将处于浏览器的默认时区。
禁用和只读状态
设置 disabled
属性将移除 <b-calendar>
组件的所有交互性。
设置 readonly
属性将禁用选择日期,但会保持组件的交互性,允许日期导航。v-model
不会在只读状态下更新。
有关禁用特定日期或设置最小和最大日期限制,请参阅 日期约束 部分。
<template>
<div>
<b-form-group label="Select calendar interactive state" v-slot="{ ariaDescribedby }">
<b-form-radio-group
v-model="state"
:aria-describedby="ariaDescribedby"
aria-controls="ex-disabled-readonly"
>
<b-form-radio value="disabled">Disabled</b-form-radio>
<b-form-radio value="readonly">Readonly</b-form-radio>
<b-form-radio value="normal">Normal</b-form-radio>
</b-form-radio-group>
</b-form-group>
<b-calendar
id="ex-disabled-readonly"
:disabled="disabled"
:readonly="readonly"
></b-calendar>
</div>
</template>
<script>
export default {
data() {
return {
state: 'disabled'
}
},
computed: {
disabled() {
return this.state === 'disabled'
},
readonly() {
return this.state === 'readonly'
}
}
}
</script>
日期约束
最小和最大日期
通过 min
和 max
属性限制日历范围。这些属性接受 YYYY-MM-DD
格式的日期字符串或 Date
对象。
<template>
<div>
<b-calendar v-model="value" :min="min" :max="max" locale="en"></b-calendar>
</div>
</template>
<script>
export default {
data() {
const now = new Date()
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
const minDate = new Date(today)
minDate.setMonth(minDate.getMonth() - 2)
minDate.setDate(15)
const maxDate = new Date(today)
maxDate.setMonth(maxDate.getMonth() + 2)
maxDate.setDate(15)
return {
value: '',
min: minDate,
max: maxDate
}
}
}
</script>
禁用日期
如果你需要禁用日历中的特定日期,请将函数引用指定给 date-disabled-fn
属性。该函数传递两个参数
ymd
日期,格式为 YYYY-MM-DD
的字符串 date
日期,格式为 Date
对象
该函数应返回 true
(如果日期不能选择(已禁用))或 false
(如果日期可以选择(已启用))。请注意,该函数不能是异步的,并且应尽快返回一个值。
<template>
<div>
<b-calendar v-model="value" :date-disabled-fn="dateDisabled" locale="en"></b-calendar>
</div>
</template>
<script>
export default {
data() {
return {
value: ''
}
},
methods: {
dateDisabled(ymd, date) {
const weekday = date.getDay()
const day = date.getDate()
return weekday === 0 || weekday === 6 || day === 13
}
}
}
</script>
请注意,在 date-disabled-fn
之前,会先评估 min
和 max
日期约束。
样式
变体
选定日期按钮(背景颜色)默认为 'primary'
主题变体。您可以通过 selected-variant
属性将其更改为任何 Bootstrap v4 主题变体颜色:'secondary'
、'success'
、'danger'
、'warning'
、'info'
等。
默认情况下,当天的日期也将使用与选定日期相同的变体(文本颜色)突出显示。要为当天的日期指定不同的主题颜色,请使用 today-variant
属性。
要完全禁用当天的日期高亮显示,请设置 no-highlight-today
属性。
导航按钮默认为 'secondary'
主题变体。您可以通过 nav-button-variant
属性更改此设置。
<template>
<b-calendar
selected-variant="success"
today-variant="info"
nav-button-variant="primary"
></b-calendar>
</template>
宽度
<b-calendar>
呈现为内联块元素,默认宽度为 270px
(不包括可能添加的任何填充或边框)。此宽度经过优化,以适应较小的移动设备的宽度。
要更改宽度,请将 width
属性设置为任何有效的 CSS 宽度(包括单位)。
或者,通过设置属性 block
使日历全宽,这将使日历扩展以适应父元素的宽度。width
属性在设置 block
时不起作用。
<template>
<b-calendar block locale="en-US"></b-calendar>
</template>
请注意,不建议将宽度设置为低于 260px
,否则可能会出现组件的截断和布局问题。
初始打开日历日期
默认情况下,当未选择日期时,日历视图将设置为当前月份(或 min
或 max
日期,如果今天的日期超出 min
或 max
的范围)。您可以通过 initial-date
属性指定日期来更改此行为。初始日期属性将用于确定最初向用户显示的日历月份。它不会设置组件的值。
v2.6.0+
要更改组件内部显示的日期文本的格式选项,例如在标题中,将 date-format-options
属性设置为包含 Intl.DateTimeFormat
对象的请求格式属性的对象(另请参阅 国际化)。
<template>
<div>
<p>Custom date format:</p>
<b-calendar
:date-format-options="{ year: 'numeric', month: 'short', day: '2-digit', weekday: 'short' }"
locale="en"
></b-calendar>
<p class="mt-3">Short date format:</p>
<b-calendar
:date-format-options="{ year: 'numeric', month: 'numeric', day: 'numeric' }"
locale="en"
></b-calendar>
</div>
</template>
下表总结了每个格式属性的有效选项
属性 | 可能的值 |
年份 | 'numeric' 或 '2-digit' |
月份 | 'numeric' 、'2-digit' 、'long' 、'short' 或 'narrow' |
天 | 'numeric' 或 '2-digit' |
星期 | 'long' 、'short' 或 'narrow' |
注释
- 省略某些选项可能会影响格式化的文本字符串,例如
weekday
- 格式化的值会根据解析的语言环境而异。某些语言环境可能不支持
'narrow'
格式,并且会回退到 'short'
或 long'
(如果 'short'
不可用) year
、month
和 day
始终会显示。如果您需要省略一个值,请将属性设置为 undefined
,尽管出于无障碍原因,强烈不建议这样做
2.12.0+
日历星期名称标题格式默认为 'short'
,它通常是星期三字符缩写,尽管某些 语言环境 可能会覆盖此格式。可以通过属性 weekday-header-format
控制格式,它接受三个值之一
'long'
完整的星期名称(例如 Tuesday)。在使用全宽日历时很方便。避免与默认日历宽度一起使用。 'short'
通常是星期名称的 2 或 3 个字母缩写,具体取决于所选的语言环境(例如“Tue”)。 'narrow'
通常是一个单字符缩写(例如,T)。对于某些语言环境,两个工作日可能具有相同的窄样式(例如,星期二和星期四的窄样式都是 T)。这对于不支持 'short'
格式的语言环境(例如语言环境 'ar'
和 'fa'
)非常方便。
默认情况下,当前选定的日期将显示在日历组件的顶部,并以语言环境的语言格式化。
你可以通过 hide-header
属性隐藏此标题。请注意,这只会从视觉上隐藏选定的日期,同时将其作为 aria-live
区域保留给屏幕阅读器用户。
有关示例用法,请参阅下面的 国际化部分。
设置属性 show-decade-nav
以启用日历的日期导航工具栏中的上一个和下一个十年按钮。
属性 label-prev-decade
和 label-next-decade
属性可用于为十年按钮提供自定义标签文本。
有关示例用法,请参阅下面的 国际化部分。
边框和内边距
想要一个带边框和内边距的日历吗?使用 Bootstrap 的 边框和内边距实用程序类 添加边框和内边距
<template>
<b-calendar class="border rounded p-2" locale="en"></b-calendar>
</template>
默认插槽
通过使用默认插槽在日历界面的底部提供可选内容。该插槽可用于添加按钮,例如 Select Today
或 Reset
等。
<template>
<b-calendar v-model="value" value-as-date locale="en">
<div class="d-flex" dir="ltr">
<b-button
size="sm"
variant="outline-danger"
v-if="value"
@click="clearDate"
>
Clear date
</b-button>
<b-button
size="sm"
variant="outline-primary"
class="ml-auto"
@click="setToday"
>
Set Today
</b-button>
</div>
</b-calendar>
</template>
<script>
export default {
data() {
return {
value: null
}
},
methods: {
setToday() {
const now = new Date()
this.value = new Date(now.getFullYear(), now.getMonth(), now.getDate())
},
clearDate() {
this.value = ''
}
}
}
</script>
2.12.0+
为了更改日历的日期导航按钮的内容,BootstrapVue 为每个按钮提供了作用域插槽
'nav-prev-decade'
'nav-prev-year'
'nav-prev-month'
'nav-this-month'
(转到选定/今天的按钮) 'nav-next-month'
'nav-next-year'
'nav-next-decade'
所有七个插槽都具有相同的可用作用域属性
属性 | 类型 | 说明 |
isRTL | 布尔值 | 当日期导航栏从右到左呈现时,将为 true |
可以使用 isRTL
作用域属性来“翻转”上一个与下一个按钮的内容,以处理从左到右到从右到左的方向变化,即当 isRTL
为 true
时,上一年按钮将位于右侧,而不是左侧。
向特定日期添加 CSS 类
如果需要突出显示特定日期,请将 date-info-fn
属性设置为对函数的引用,该函数返回要应用于日期单元格的 CSS 类字符串(或字符串数组)。该函数传递两个参数
ymd
日期,格式为 YYYY-MM-DD
的字符串 date
日期,格式为 Date
对象
该函数可以返回一个字符串或一个字符串数组。如果不设置任何类,则可以返回一个空字符串 (''
)、空数组 ([]
) 或 null
。
在此示例中,我们使用 table-{variant}
颜色类在日期单元格上设置背景颜色。 table-{variant}
颜色类效果很好,因为它们是主题颜色的柔和版本。
<template>
<div>
<b-calendar v-model="value" :date-info-fn="dateClass" locale="en"></b-calendar>
</div>
</template>
<script>
export default {
data() {
return {
value: ''
}
},
methods: {
dateClass(ymd, date) {
const day = date.getDate()
return day >= 10 && day <= 20 ? 'table-info' : ''
}
}
}
</script>
请注意,对于已禁用日期,不会调用该函数。
辅助功能说明
当使用类向日期传达特定含义时,应在日历外部(或通过默认插槽)包含其他上下文,以说明正在突出显示的日期(例如在 aria-live
区域中),特别是对于屏幕阅读器用户。
BootstrapVue 可能在未来添加一项功能,通过此函数在突出显示的日期上添加屏幕阅读器友好的文本说明。
事件
更新 v-model
时会触发 'input'
事件。该事件有一个参数,即所选日期。默认情况下,该值是 YYYY-MM-DD
格式的字符串(如果未选择日期,则为空字符串)。如果设置了 value-as-date
属性,则第一个参数将改为 Date
对象(如果未选择日期,则为 null
)。
如果设置了 disabled
或 readonly
属性,则不会触发 'input'
事件。
selected
事件
当用户单击未禁用的日期时,会发出 'selected'
事件。该事件传递两个参数
ymd
以 YYYY-MM-DD
字符串形式表示的所选日期 date
以 Date
对象形式表示的所选日期
如果用户单击已选日期,则仍会发出 selected
事件,与 'input'
事件相反,后者不会重新发出已选日期。
如果设置了 disabled
或 readonly
属性,则不会发出 'selected'
事件。
context
事件
每当用户选择日期或用户浏览日历(通过光标键、向上/向下翻页键、主页或结束键,或使用日历导航按钮)时,都会发出 'context'
事件。当组件创建(在插入到 DOM 之前)或已解析的语言环境发生更改时,也会发出此事件。
当设置 readonly
属性时,当用户浏览日历时,仍会发出该事件。当设置 disabled
属性时,不会发出该事件(日历创建时的初始发出除外)。
'context'
事件传递一个上下文对象作为其唯一参数,该对象具有以下属性
属性 | 说明 |
selectedYMD | 所选日期值(YYYY-MM-DD 格式)或空字符串(如果未选择日期) |
selectedDate | 所选日期值(Date 对象)或 null (如果未选择日期) |
selectedFormatted | 以当前语言环境格式化的所选日期。如果未选择日期,则此值将为 label-no-date-selected 属性的值 |
activeYMD | 可以接收焦点的日历日按钮的当前日期(YYYY-MM-DD 格式) |
activeDate | 可以接收焦点的日历日按钮的当前日期(Date 对象) |
activeFormatted | 当前区域设置中格式化的活动日期 |
disabled | 如果活动日期被禁用,则为 true ,否则为 false |
locale | 已解析的区域设置(可能与请求的区域设置不同) |
calendarLocale | 日历使用的已解析区域设置,可以选择性地包括日历类型(即“公历”)。通常这与 locale 相同,但可能包括所使用的日历类型,例如在选择波斯区域设置('fa' )时为 fa-u-ca-gregory |
isRTL | 如果日历以 RTL(从右到左)方向显示,则为 true 。如果为 LTR(从左到右),则为 false |
如果通过 Intl.DateTimeFormat
手动设置日期格式,请使用 calendarLocale
属性值,而不是 locale
属性值,以确保使用与 <b-calendar>
相同的日历惯例。对于 IE 11 浏览器来说尤其如此,因为它没有完全实现 Intl.DateTimeFormat
的所有功能。有关其他详细信息,请参阅下面的 国际化部分。
国际化
日历的国际化通过 Intl.DateTimeFormat
提供,日历控件元素的标签(aria 标签、已选择状态和帮助文本)除外。您必须为这些标签提供自己的翻译。可用的区域设置取决于浏览器(并非所有浏览器都支持所有区域设置)
默认情况下,<b-calendar>
将使用浏览器的默认区域设置,但您可以通过 locale
属性指定要使用的区域设置(或区域设置)。该属性接受单个区域设置字符串或区域设置字符串数组(按首选区域设置的顺序排列)。
日历从星期日开始。可以通过将 start-weekday
属性设置为 0
到 6
范围内的数字来更改此设置,其中 0
表示星期日,1
表示星期一,依此类推,6
表示星期六。
发出的 context
事件将包含日历已解析到的语言环境(可能与请求的语言环境不同,具体取决于 Intl
支持的语言环境)。
<template>
<b-row>
<b-col cols="12" class="mb-3">
<label for="example-locales">Locale:</label>
<b-form-select id="example-locales" v-model="locale" :options="locales"></b-form-select>
<label for="example-weekdays" class="mt-2">Start weekday:</label>
<b-form-select id="example-weekdays" v-model="weekday" :options="weekdays"></b-form-select>
<b-form-checkbox v-model="showDecadeNav" switch inline class="my-2">
Show decade navigation buttons
</b-form-checkbox>
<b-form-checkbox v-model="hideHeader" switch inline class="my-2">
Hide the date header
</b-form-checkbox>
</b-col>
<b-col md="auto">
<b-calendar
v-model="value"
v-bind="labels[locale] || {}"
:locale="locale"
:start-weekday="weekday"
:hide-header="hideHeader"
:show-decade-nav="showDecadeNav"
@context="onContext"
></b-calendar>
</b-col>
<b-col>
<p>Value: <b>'{{ value }}'</b></p>
<p class="mb-0">Context:</p>
<pre class="small">{{ context }}</pre>
</b-col>
</b-row>
</template>
<script>
export default {
data() {
return {
value: '',
context: null,
showDecadeNav: false,
hideHeader: false,
locale: 'en-US',
locales: [
{ value: 'en-US', text: 'English US (en-US)' },
{ value: 'de', text: 'German (de)' },
{ value: 'ar-EG', text: 'Arabic Egyptian (ar-EG)' },
{ value: 'zh', text: 'Chinese (zh)' }
],
weekday: 0,
weekdays: [
{ value: 0, text: 'Sunday' },
{ value: 1, text: 'Monday' },
{ value: 6, text: 'Saturday' }
],
labels: {
de: {
labelPrevDecade: 'Vorheriges Jahrzehnt',
labelPrevYear: 'Vorheriges Jahr',
labelPrevMonth: 'Vorheriger Monat',
labelCurrentMonth: 'Aktueller Monat',
labelNextMonth: 'Nächster Monat',
labelNextYear: 'Nächstes Jahr',
labelNextDecade: 'Nächstes Jahrzehnt',
labelToday: 'Heute',
labelSelected: 'Ausgewähltes Datum',
labelNoDateSelected: 'Kein Datum gewählt',
labelCalendar: 'Kalender',
labelNav: 'Kalendernavigation',
labelHelp: 'Mit den Pfeiltasten durch den Kalender navigieren'
},
'ar-EG': {
weekdayHeaderFormat: 'narrow',
labelPrevDecade: 'العقد السابق',
labelPrevYear: 'العام السابق',
labelPrevMonth: 'الشهر السابق',
labelCurrentMonth: 'الشهر الحالي',
labelNextMonth: 'الشهر المقبل',
labelNextYear: 'العام المقبل',
labelNextDecade: 'العقد القادم',
labelToday: 'اليوم',
labelSelected: 'التاريخ المحدد',
labelNoDateSelected: 'لم يتم اختيار تاريخ',
labelCalendar: 'التقويم',
labelNav: 'الملاحة التقويم',
labelHelp: 'استخدم مفاتيح المؤشر للتنقل في التواريخ'
},
zh: {
weekdayHeaderFormat: 'narrow',
labelPrevDecade: '过去十年',
labelPrevYear: '上一年',
labelPrevMonth: '上个月',
labelCurrentMonth: '当前月份',
labelNextMonth: '下个月',
labelNextYear: '明年',
labelNextDecade: '下一个十年',
labelToday: '今天',
labelSelected: '选定日期',
labelNoDateSelected: '未选择日期',
labelCalendar: '日历',
labelNav: '日历导航',
labelHelp: '使用光标键浏览日期'
}
}
}
},
methods: {
onContext(ctx) {
this.context = ctx
}
}
}
</script>
目前,<b-calendar>
仅支持公历('gregory'
)。
默认情况下,<b-calendar>
通过已解析的语言环境自动检测 RTL 与 LTR。可以通过将 direction
属性设置为字符串 rtl
来强制日历从右到左呈现,或将 direction
属性设置为 'ltr'
来始终从左到右呈现。
你可以监听 context
事件以确定日历已解析到的语言环境和方向性。
对于使用 Node.js 的服务器端渲染 (SSR),请确保你使用的 Node.js 运行时支持 Intl
和你将使用的语言环境。有关详细信息,请参阅 Node Intl
支持文档。
辅助功能
<b-calendar>
提供了许多辅助功能,例如 aria-live
区域、角色、aria 标签、快捷键和完整的键盘导航,以便与大多数屏幕阅读器配合使用。
键盘导航
- ArrowLeft 移至前一天(或在 RTL 模式下移至后一天)
- ArrowRight 移至后一天(或在 RTL 模式下移至前一天)
- ArrowUp 移至前一周的同一天
- ArrowDown 移至后一周的同一天
- PageUp 移至前一个月的同一天
- PageDown 移至后一个月的同一天
- Alt+PageUp 移至前一年的同一天和月份
- Alt+PageDown 移至后一年的同一天和月份
- Ctrl+Alt+PageUp 移至上一个十年的同一天和月份
- Ctrl+Alt+PageDown 移至下一个十年的同一天和月份
- Home 移至今天的日期
- End 移至当前选定的日期,如果没有选定日期,则移至今天
- Enter 或 Space 选择当前高亮(焦点)的日期
几个 label-*
道具在屏幕上不可见,但用于为屏幕阅读器用户标记日历中的各种元素。例如,label-today
道具被添加到包含今天的日期的单元格中:'2020 年 1 月 28 日(今天)'
,而 label-selected
道具被添加到包含选定日期的单元格中 '2020 年 1 月 28 日(选定日期)'
,并作为 sr-only
文本添加到选定日期标题中。
在对日期选择器进行国际化时,重要的是还要使用适当的翻译字符串更新 label-*
道具,以便国际屏幕阅读器用户能够听到正确的提示和描述。
<b-calendar>
的功能和样式故意保持简约,以便为所有用户提供尽可能好的可访问性。
实现说明
<b-calendar>
使用 Bootstrap 的边框和 flex 实用程序类,以及按钮 (btn-*
) 类和 form-control
类。BootstrapVue 的自定义 SCSS/CSS 也需要用于正确的样式。
在可访问性方面,我们选择不对日历使用 ARIA 角色 grid
,以最大程度减少冗长性,并在各种屏幕阅读器(NVDA,在遇到角色 grid
时,将焦点单元格读为“已选择”,这可能会对用户造成误导)中提供一致性。
另请参见