mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-05 19:41:42 +08:00
feat(Pagination): refactor DOM to improve a11y (#9901)
This commit is contained in:
parent
42a5f79c2c
commit
3885fd00ed
@ -1,10 +1,11 @@
|
||||
import { computed, watch, defineComponent, ExtractPropTypes } from 'vue';
|
||||
import { computed, watchEffect, defineComponent, ExtractPropTypes } from 'vue';
|
||||
import {
|
||||
BORDER,
|
||||
clamp,
|
||||
makeStringProp,
|
||||
makeNumberProp,
|
||||
makeNumericProp,
|
||||
createNamespace,
|
||||
BORDER_SURROUND,
|
||||
} from '../utils';
|
||||
|
||||
const [name, bem, t] = createNamespace('pagination');
|
||||
@ -57,10 +58,6 @@ export default defineComponent({
|
||||
const showPageSize = +props.showPageSize;
|
||||
const { modelValue, forceEllipses } = props;
|
||||
|
||||
if (props.mode !== 'multi') {
|
||||
return items;
|
||||
}
|
||||
|
||||
// Default page limits
|
||||
let startPage = 1;
|
||||
let endPage = pageCount;
|
||||
@ -101,85 +98,96 @@ export default defineComponent({
|
||||
return items;
|
||||
});
|
||||
|
||||
const select = (page: number, emitChange?: boolean) => {
|
||||
page = Math.min(count.value, Math.max(1, page));
|
||||
const updateModelValue = (value: number, emitChange?: boolean) => {
|
||||
value = clamp(value, 1, count.value);
|
||||
|
||||
if (props.modelValue !== page) {
|
||||
emit('update:modelValue', page);
|
||||
if (props.modelValue !== value) {
|
||||
emit('update:modelValue', value);
|
||||
|
||||
if (emitChange) {
|
||||
emit('change', page);
|
||||
emit('change', value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(value) => {
|
||||
select(value);
|
||||
},
|
||||
{ immediate: true }
|
||||
// format modelValue
|
||||
watchEffect(() => updateModelValue(props.modelValue));
|
||||
|
||||
const renderDesc = () => (
|
||||
<li class={bem('page-desc')}>
|
||||
{slots.pageDesc
|
||||
? slots.pageDesc()
|
||||
: `${props.modelValue}/${count.value}`}
|
||||
</li>
|
||||
);
|
||||
|
||||
const renderDesc = () => {
|
||||
if (props.mode !== 'multi') {
|
||||
return (
|
||||
<li class={bem('page-desc')}>
|
||||
{slots.pageDesc
|
||||
? slots.pageDesc()
|
||||
: `${props.modelValue}/${count.value}`}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return () => {
|
||||
const value = props.modelValue;
|
||||
const simple = props.mode !== 'multi';
|
||||
|
||||
const onSelect = (value: number) => () => select(value, true);
|
||||
|
||||
const renderPrevButton = () => {
|
||||
const { mode, modelValue } = props;
|
||||
const slot = slots['prev-text'];
|
||||
const disabled = modelValue === 1;
|
||||
return (
|
||||
<ul class={bem({ simple })}>
|
||||
<li
|
||||
class={[
|
||||
bem('item', { disabled: value === 1 }),
|
||||
bem('prev'),
|
||||
BORDER,
|
||||
]}
|
||||
onClick={onSelect(value - 1)}
|
||||
<li
|
||||
class={[
|
||||
bem('item', { disabled, border: mode === 'simple', prev: true }),
|
||||
BORDER_SURROUND,
|
||||
]}
|
||||
>
|
||||
<button
|
||||
disabled={disabled}
|
||||
onClick={() => updateModelValue(modelValue - 1)}
|
||||
>
|
||||
{slots['prev-text']
|
||||
? slots['prev-text']()
|
||||
: props.prevText || t('prev')}
|
||||
</li>
|
||||
{pages.value.map((page) => (
|
||||
<li
|
||||
class={[
|
||||
bem('item', { active: page.active }),
|
||||
bem('page'),
|
||||
BORDER,
|
||||
]}
|
||||
onClick={onSelect(page.number)}
|
||||
>
|
||||
{slots.page ? slots.page(page) : page.text}
|
||||
</li>
|
||||
))}
|
||||
{renderDesc()}
|
||||
<li
|
||||
class={[
|
||||
bem('item', { disabled: value === count.value }),
|
||||
bem('next'),
|
||||
BORDER,
|
||||
]}
|
||||
onClick={onSelect(value + 1)}
|
||||
>
|
||||
{slots['next-text']
|
||||
? slots['next-text']()
|
||||
: props.nextText || t('next')}
|
||||
</li>
|
||||
</ul>
|
||||
{slot ? slot() : props.prevText || t('prev')}
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
const renderNextButton = () => {
|
||||
const { mode, modelValue } = props;
|
||||
const slot = slots['next-text'];
|
||||
const disabled = modelValue === count.value;
|
||||
return (
|
||||
<li
|
||||
class={[
|
||||
bem('item', { disabled, border: mode === 'simple', next: true }),
|
||||
BORDER_SURROUND,
|
||||
]}
|
||||
>
|
||||
<button
|
||||
disabled={disabled}
|
||||
onClick={() => updateModelValue(modelValue + 1)}
|
||||
>
|
||||
{slot ? slot() : props.nextText || t('next')}
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
const renderPages = () =>
|
||||
pages.value.map((page) => (
|
||||
<li
|
||||
class={[
|
||||
bem('item', { active: page.active, page: true }),
|
||||
BORDER_SURROUND,
|
||||
]}
|
||||
>
|
||||
<button
|
||||
aria-current={page.active || undefined}
|
||||
onClick={() => updateModelValue(page.number)}
|
||||
>
|
||||
{slots.page ? slots.page(page) : page.text}
|
||||
</button>
|
||||
</li>
|
||||
));
|
||||
|
||||
return () => (
|
||||
<nav role="navigation" class={bem()}>
|
||||
<ul class={bem('items')}>
|
||||
{renderPrevButton()}
|
||||
{props.mode === 'simple' ? renderDesc() : renderPages()}
|
||||
{renderNextButton()}
|
||||
</ul>
|
||||
</nav>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
@ -13,9 +13,12 @@
|
||||
}
|
||||
|
||||
.van-pagination {
|
||||
display: flex;
|
||||
font-size: var(--van-pagination-font-size);
|
||||
|
||||
&__items {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&__item,
|
||||
&__page-desc {
|
||||
display: flex;
|
||||
@ -33,58 +36,56 @@
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
border: none;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
|
||||
&[disabled] {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: var(--van-white);
|
||||
background-color: var(--van-pagination-item-default-color);
|
||||
}
|
||||
|
||||
&::after {
|
||||
border-width: var(--van-border-width-base) 0 var(--van-border-width-base)
|
||||
var(--van-border-width-base);
|
||||
}
|
||||
|
||||
&:last-child::after {
|
||||
border-right-width: var(--van-border-width-base);
|
||||
&:not(:last-child)::after {
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
&--active {
|
||||
color: var(--van-white);
|
||||
background-color: var(--van-pagination-item-default-color);
|
||||
}
|
||||
}
|
||||
|
||||
&__prev,
|
||||
&__next {
|
||||
padding: 0 var(--van-padding-base);
|
||||
cursor: pointer;
|
||||
}
|
||||
&--page {
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
&__item--disabled {
|
||||
&,
|
||||
&:active {
|
||||
&--prev,
|
||||
&--next {
|
||||
padding: 0 var(--van-padding-base);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&--border::after {
|
||||
border-width: var(--van-border-width-base);
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
color: var(--van-pagination-item-disabled-color);
|
||||
background-color: var(--van-pagination-item-disabled-background-color);
|
||||
cursor: not-allowed;
|
||||
opacity: var(--van-pagination-disabled-opacity);
|
||||
}
|
||||
}
|
||||
|
||||
&__page {
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
&__page-desc {
|
||||
flex: 1;
|
||||
height: var(--van-pagination-height);
|
||||
color: var(--van-pagination-desc-color);
|
||||
}
|
||||
|
||||
&--simple {
|
||||
.van-pagination__prev,
|
||||
.van-pagination__next {
|
||||
&::after {
|
||||
border-width: var(--van-border-width-base);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,92 +2,151 @@
|
||||
|
||||
exports[`should render demo and match snapshot 1`] = `
|
||||
<div>
|
||||
<ul class="van-pagination">
|
||||
<li class="van-pagination__item van-pagination__item--disabled van-pagination__prev van-hairline">
|
||||
Prev
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--active van-pagination__page van-hairline">
|
||||
1
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
2
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
3
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
4
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
5
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__next van-hairline">
|
||||
Next
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="van-pagination van-pagination--simple"
|
||||
size="small"
|
||||
<nav role="navigation"
|
||||
class="van-pagination"
|
||||
>
|
||||
<li class="van-pagination__item van-pagination__item--disabled van-pagination__prev van-hairline">
|
||||
Prev
|
||||
</li>
|
||||
<li class="van-pagination__page-desc">
|
||||
1/12
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__next van-hairline">
|
||||
Next
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="van-pagination__items">
|
||||
<li class="van-pagination__item van-pagination__item--disabled van-pagination__item--prev van-hairline--surround">
|
||||
<button disabled>
|
||||
Prev
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--active van-pagination__item--page van-hairline--surround">
|
||||
<button aria-current="true">
|
||||
1
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
2
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
3
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
4
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
5
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--next van-hairline--surround">
|
||||
<button>
|
||||
Next
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="van-pagination">
|
||||
<li class="van-pagination__item van-pagination__item--disabled van-pagination__prev van-hairline">
|
||||
Prev
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--active van-pagination__page van-hairline">
|
||||
1
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
2
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
3
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
...
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__next van-hairline">
|
||||
Next
|
||||
</li>
|
||||
</ul>
|
||||
<nav role="navigation"
|
||||
class="van-pagination"
|
||||
size="small"
|
||||
>
|
||||
<ul class="van-pagination__items">
|
||||
<li class="van-pagination__item van-pagination__item--disabled van-pagination__item--border van-pagination__item--prev van-hairline--surround">
|
||||
<button disabled>
|
||||
Prev
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__page-desc">
|
||||
1/12
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--border van-pagination__item--next van-hairline--surround">
|
||||
<button>
|
||||
Next
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="van-pagination">
|
||||
<li class="van-pagination__item van-pagination__item--disabled van-pagination__prev van-hairline">
|
||||
<i class="van-badge__wrapper van-icon van-icon-arrow-left">
|
||||
</i>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--active van-pagination__page van-hairline">
|
||||
1
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
2
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
3
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
4
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
5
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__next van-hairline">
|
||||
<i class="van-badge__wrapper van-icon van-icon-arrow">
|
||||
</i>
|
||||
</li>
|
||||
</ul>
|
||||
<nav role="navigation"
|
||||
class="van-pagination"
|
||||
>
|
||||
<ul class="van-pagination__items">
|
||||
<li class="van-pagination__item van-pagination__item--disabled van-pagination__item--prev van-hairline--surround">
|
||||
<button disabled>
|
||||
Prev
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--active van-pagination__item--page van-hairline--surround">
|
||||
<button aria-current="true">
|
||||
1
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
2
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
3
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
...
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--next van-hairline--surround">
|
||||
<button>
|
||||
Next
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div>
|
||||
<nav role="navigation"
|
||||
class="van-pagination"
|
||||
>
|
||||
<ul class="van-pagination__items">
|
||||
<li class="van-pagination__item van-pagination__item--disabled van-pagination__item--prev van-hairline--surround">
|
||||
<button disabled>
|
||||
<i class="van-badge__wrapper van-icon van-icon-arrow-left">
|
||||
</i>
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--active van-pagination__item--page van-hairline--surround">
|
||||
<button aria-current="true">
|
||||
1
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
2
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
3
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
4
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
5
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--next van-hairline--surround">
|
||||
<button>
|
||||
<i class="van-badge__wrapper van-icon van-icon-arrow">
|
||||
</i>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
`;
|
||||
|
@ -1,53 +1,89 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`should render page slot correctly 1`] = `
|
||||
<ul class="van-pagination">
|
||||
<li class="van-pagination__item van-pagination__prev van-hairline">
|
||||
Previous
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
foo 1
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
foo 2
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
foo 3
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
foo 4
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
foo 5
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__next van-hairline">
|
||||
Next
|
||||
</li>
|
||||
</ul>
|
||||
<nav role="navigation"
|
||||
class="van-pagination"
|
||||
>
|
||||
<ul class="van-pagination__items">
|
||||
<li class="van-pagination__item van-pagination__item--prev van-hairline--surround">
|
||||
<button>
|
||||
Previous
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
foo 1
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
foo 2
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
foo 3
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
foo 4
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
foo 5
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--next van-hairline--surround">
|
||||
<button>
|
||||
Next
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
`;
|
||||
|
||||
exports[`should render prev-text、next-text slot correctly 1`] = `
|
||||
<ul class="van-pagination">
|
||||
<li class="van-pagination__item van-pagination__prev van-hairline">
|
||||
Custom PrevText
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
1
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
2
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
3
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
4
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__page van-hairline">
|
||||
5
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__next van-hairline">
|
||||
Custom NextText
|
||||
</li>
|
||||
</ul>
|
||||
<nav role="navigation"
|
||||
class="van-pagination"
|
||||
>
|
||||
<ul class="van-pagination__items">
|
||||
<li class="van-pagination__item van-pagination__item--prev van-hairline--surround">
|
||||
<button>
|
||||
Custom PrevText
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
1
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
2
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
3
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
4
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--page van-hairline--surround">
|
||||
<button>
|
||||
5
|
||||
</button>
|
||||
</li>
|
||||
<li class="van-pagination__item van-pagination__item--next van-hairline--surround">
|
||||
<button>
|
||||
Custom NextText
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
`;
|
||||
|
Loading…
x
Reference in New Issue
Block a user