Skip to content

Commit e04291f

Browse files
authored
perf(pagination+pagination-nav): convert templates to render function (#1348)
* perf(pagination-nav): convert template to render function * [pagination mixn] create common render function * [pagination] Use mixin render function * [pagination-nav] use mixin render function
1 parent 9d0ae3e commit e04291f

File tree

3 files changed

+208
-260
lines changed

3 files changed

+208
-260
lines changed

src/components/pagination-nav/pagination-nav.vue

Lines changed: 20 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,133 +1,22 @@
1-
<template>
2-
<nav>
3-
<ul :class="['pagination',btnSize,alignment]"
4-
:aria-disabled="disabled ? 'true' : 'false'"
5-
:aria-label="ariaLabel ? ariaLabel : null"
6-
role="menubar"
7-
tabindex="0"
8-
@keydown.left.prevent="focusPrev"
9-
@keydown.right.prevent="focusNext"
10-
@keydown.shift.left.prevent="focusFirst"
11-
@keydown.shift.right.prevent="focusLast"
12-
>
13-
14-
<!-- Goto First Page button -->
15-
<template v-if="!hideGotoEndButtons">
16-
<li v-if="isActive(1) || disabled" class="page-item disabled" role="none presentation" aria-hidden="true">
17-
<span class="page-link" v-html="firstText"></span>
18-
</li>
19-
<li v-else class="page-item" role="none presentation">
20-
<b-link class="page-link"
21-
v-bind="linkProps(1)"
22-
:aria-label="labelFirstPage"
23-
role="menuitem"
24-
tabindex="-1"
25-
@click="onClick(1)"
26-
><span aria-hidden="true" v-html="firstText"></span></b-link>
27-
</li>
28-
</template>
29-
30-
<!-- Goto Previous page button -->
31-
<li v-if="isActive(1) || disabled" class="page-item disabled" role="none presentation" aria-hidden="true">
32-
<span class="page-link" v-html="prevText"></span>
33-
</li>
34-
<li v-else class="page-item" role="none presentation">
35-
<b-link class="page-link"
36-
v-bind="linkProps(currentPage - 1)"
37-
:aria-label="labelPrevPage"
38-
role="menuitem"
39-
tabindex="-1"
40-
@click="onClick(currentPage - 1)"
41-
><span aria-hidden="true" v-html="prevText"></span></b-link>
42-
</li>
43-
44-
<!-- First Ellipsis Bookend -->
45-
<li v-if="showFirstDots" class="page-item disabled d-none d-sm-flex" role="separator">
46-
<span class="page-link" v-html="ellipsisText"></span>
47-
</li>
48-
49-
<!-- Pages links -->
50-
<li v-for="page in pageList" role="none presentation" :class="pageItemClasses(page)" :key="page.number">
51-
<span v-if="disabled" class="page-link">{{ page.number }}</span>
52-
<b-link v-else
53-
v-bind="linkProps(page.number)"
54-
:class="pageLinkClasses(page)"
55-
:disabled="disabled"
56-
:aria-disabled="disabled ? 'true' : null"
57-
:aria-label="labelPage + ' ' + page.number"
58-
:aria-checked="isActive(page.number) ? 'true' : 'false'"
59-
:aria-posinset="page.number"
60-
:aria-setsize="numberOfPages"
61-
role="menuitemradio"
62-
:tabindex="isActive(page.number) ? '0' : '-1'"
63-
@click="onClick(page.number)"
64-
v-html="makePage(page.number)"
65-
></b-link>
66-
</li>
67-
68-
<!-- Last Ellipsis Bookend -->
69-
<li v-if="showLastDots" class="page-item disabled d-none d-sm-flex" role="separator">
70-
<span class="page-link" v-html="ellipsisText"></span>
71-
</li>
72-
73-
<!-- Goto Next page -->
74-
<li v-if="isActive(numberOfPages) || disabled" class="page-item disabled" role="none presentation" aria-hidden="true">
75-
<span class="page-link" v-html="nextText"></span>
76-
</li>
77-
<li v-else class="page-item" role="none presentation">
78-
<b-link class="page-link"
79-
v-bind="linkProps(currentPage + 1)"
80-
:aria-label="labelNextPage"
81-
role="menuitem"
82-
tabindex="-1"
83-
@click="onClick(currentPage + 1)"
84-
><span aria-hidden="true" v-html="nextText"></span></b-link>
85-
</li>
86-
87-
<!-- Goto Last page -->
88-
<template v-if="!hideGotoEndButtons">
89-
<li v-if="isActive(numberOfPages) || disabled"
90-
class="page-item disabled"
91-
role="none presentation"
92-
aria-hidden="true"
93-
>
94-
<span class="page-link" v-html="lastText"></span>
95-
</li>
96-
<li v-else class="page-item" role="none presentation">
97-
<b-link class="page-link"
98-
v-bind="linkProps(numberOfPages)"
99-
:aria-label="labelLastPage"
100-
role="menuitem"
101-
tabindex="-1"
102-
@click="onClick(numberOfPages)"
103-
><span aria-hidden="true" v-html="lastText"></span></b-link>
104-
</li>
105-
</template>
106-
</ul>
107-
</nav>
108-
</template>
109-
110-
<style scoped>
111-
.page-item {
112-
-webkit-user-select: none;
113-
-moz-user-select: none;
114-
-ms-user-select: none;
1+
<style>
2+
.b-pagination .page-item {
1153
user-select: none;
1164
}
117-
.page-item.disabled {
5+
.b-pagination .page-item.disabled {
1186
cursor: not-allowed;
1197
opacity: .65;
1208
}
121-
.page-item .page-link.active:focus {
9+
.b-pagination .page-item .page-link.active:focus {
12210
box-shadow: 0 0 0 3px rgba(0,123,255,.5);
12311
z-index: 1;
12412
}
12513
</style>
12614

12715
<script>
128-
import bLink, { pickLinkProps } from '../link/link';
12916
import { assign } from '../../utils/object';
17+
import { KeyCodes } from '../../utils';
13018
import { paginationMixin } from '../../mixins';
19+
import { pickLinkProps } from '../link/link';
13120
13221
// Props needed for router links
13322
const routerProps = pickLinkProps('activeClass','exactActiveClass','append','exact','replace','target','rel');
@@ -161,27 +50,33 @@ const props = assign(
16150
routerProps
16251
);
16352
53+
// Our render function is brought in via the pagination mixin
16454
export default {
165-
components: { bLink },
16655
mixins: [ paginationMixin ],
16756
props,
57+
computed: {
58+
// Used by render function to trigger wraping in '<nav>' element
59+
isNav() {
60+
return true;
61+
}
62+
},
16863
methods: {
169-
onClick(pageNum) {
64+
onClick(pageNum, evt) {
17065
this.currentPage = pageNum;
17166
},
67+
makePage(pagenum) {
68+
if (this.pageGen && typeof this.pageGen === 'function') {
69+
return this.pageGen(pagenum);
70+
}
71+
return pagenum;
72+
},
17273
makeLink(pagenum) {
17374
if (this.linkGen && typeof this.linkGen === 'function') {
17475
return this.linkGen(pagenum);
17576
}
17677
const link = `${this.baseUrl}${pagenum}`;
17778
return this.useRouter ? { path: link } : link;
17879
},
179-
makePage(pagenum) {
180-
if (this.pageGen && typeof this.pageGen === 'function') {
181-
return this.pageGen(pagenum);
182-
}
183-
return pagenum;
184-
},
18580
linkProps(pagenum) {
18681
const link = this.makeLink(pagenum);
18782
let props = {

src/components/pagination/pagination.vue

Lines changed: 21 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,133 +1,15 @@
1-
<template>
2-
<ul :class="['pagination',btnSize,alignment]"
3-
:aria-disabled="disabled ? 'true' : 'false'"
4-
:aria-label="ariaLabel ? ariaLabel : null"
5-
role="menubar"
6-
@keydown.left.prevent="focusPrev"
7-
@keydown.right.prevent="focusNext"
8-
@keydown.shift.left.prevent="focusFirst"
9-
@keydown.shift.right.prevent="focusLast"
10-
>
11-
12-
<!-- Goto First Page button -->
13-
<template v-if="!hideGotoEndButtons">
14-
<li v-if="isActive(1) || disabled" class="page-item disabled" role="none presentation" aria-hidden="true">
15-
<span class="page-link" v-html="firstText"></span>
16-
</li>
17-
<li v-else class="page-item" role="none presentation">
18-
<a class="page-link"
19-
:aria-label="labelFirstPage"
20-
:aria-controls="ariaControls || null"
21-
role="menuitem"
22-
href="#"
23-
tabindex="-1"
24-
@click.prevent="setPage($event, 1)"
25-
@keydown.enter.prevent="setPage($event, 1)"
26-
@keydown.space.prevent="setPage($event, 1)"
27-
><span aria-hidden="true" v-html="firstText"></span></a>
28-
</li>
29-
</template>
30-
31-
<!-- Goto Previous page button -->
32-
<li v-if="isActive(1) || disabled" class="page-item disabled" role="none presentation" aria-hidden="true">
33-
<span class="page-link" v-html="prevText"></span>
34-
</li>
35-
<li v-else class="page-item" role="none presentation">
36-
<a class="page-link"
37-
:aria-label="labelPrevPage"
38-
:aria-controls="ariaControls || null"
39-
role="menuitem"
40-
href="#"
41-
tabindex="-1"
42-
@click.prevent="setPage($event, currentPage - 1)"
43-
@keydown.enter.prevent="setPage($event, currentPage - 1)"
44-
@keydown.space.prevent="setPage($event, currentPage - 1)"
45-
><span aria-hidden="true" v-html="prevText"></span></a>
46-
</li>
47-
48-
<!-- First Ellipsis Bookend -->
49-
<li v-if="showFirstDots" class="page-item disabled d-none d-sm-flex" role="separator">
50-
<span class="page-link" v-html="ellipsisText"></span>
51-
</li>
52-
53-
<!-- Pages links -->
54-
<li v-for="page in pageList" role="none presentation" :class="pageItemClasses(page)" :key="page.number">
55-
<a :class="pageLinkClasses(page)"
56-
:disabled="disabled"
57-
:aria-disabled="disabled ? 'true' : null"
58-
:aria-label="labelPage + ' ' + page.number"
59-
:aria-checked="isActive(page.number) ? 'true' : 'false'"
60-
:aria-controls="ariaControls || null"
61-
:aria-posinset="page.number"
62-
:aria-setsize="numberOfPages"
63-
role="menuitemradio"
64-
href="#"
65-
:tabindex="isActive(page.number) ? '0' : '-1'"
66-
@click.prevent="setPage($event, page.number)"
67-
@keydown.enter.prevent="setPage($event, page.number)"
68-
@keydown.space.prevent="setPage($event, page.number)"
69-
>{{ page.number }}</a>
70-
</li>
71-
72-
<!-- Last Ellipsis Bookend -->
73-
<li v-if="showLastDots" class="page-item disabled d-none d-sm-flex" role="separator">
74-
<span class="page-link" v-html="ellipsisText"></span>
75-
</li>
76-
77-
<!-- Goto Next page -->
78-
<li v-if="isActive(numberOfPages) || disabled" class="page-item disabled" role="none presentation" aria-hidden="true">
79-
<span class="page-link" v-html="nextText"></span>
80-
</li>
81-
<li v-else class="page-item" role="none presentation">
82-
<a class="page-link"
83-
:aria-label="labelNextPage"
84-
:aria-controls="ariaControls || null"
85-
role="menuitem"
86-
href="#"
87-
tabindex="-1"
88-
@click.prevent="setPage($event, currentPage + 1)"
89-
@keydown.enter.prevent="setPage($event, currentPage + 1)"
90-
@keydown.space.prevent="setPage($event, currentPage + 1)"
91-
><span aria-hidden="true" v-html="nextText"></span></a>
92-
</li>
93-
94-
<!-- Goto Last page -->
95-
<template v-if="!hideGotoEndButtons">
96-
<li v-if="isActive(numberOfPages) || disabled"
97-
class="page-item disabled"
98-
role="none presentation"
99-
aria-hidden="true"
100-
>
101-
<span class="page-link" v-html="lastText"></span>
102-
</li>
103-
<li v-else class="page-item" role="none presentation">
104-
<a class="page-link"
105-
:aria-label="labelLastPage"
106-
:aria-controls="ariaControls || null"
107-
role="menuitem"
108-
href="#"
109-
tabindex="-1"
110-
@click.prevent="setPage($event, numberOfPages)"
111-
@keydown.enter.prevent="setPage($event, numberOfPages)"
112-
@keydown.space.prevent="setPage($event, numberOfPages)"
113-
><span aria-hidden="true" v-html="lastText"></span></a>
114-
</li>
115-
</template>
116-
</ul>
117-
</template>
118-
119-
<style scoped>
120-
.page-item {
1+
<style>
2+
.b-pagination .page-item {
1213
-webkit-user-select: none;
1224
-moz-user-select: none;
1235
-ms-user-select: none;
1246
user-select: none;
1257
}
126-
.page-item.disabled {
8+
.b-pagination .page-item.disabled {
1279
cursor: not-allowed;
12810
opacity: .65;
12911
}
130-
.page-item .page-link.active:focus {
12+
.b-pagination .page-item .page-link.active:focus {
13113
box-shadow: 0 0 0 3px rgba(0,123,255,.5);
13214
z-index: 1;
13315
}
@@ -136,6 +18,7 @@
13618
<script>
13719
import { paginationMixin } from '../../mixins';
13820
import { isVisible } from '../../utils/dom';
21+
import { KeyCodes } from '../../utils';
13922
14023
const props = {
14124
perPage: {
@@ -152,6 +35,7 @@ const props = {
15235
}
15336
};
15437
38+
// Our render function is brought in from the pagination mixin
15539
export default {
15640
mixins: [ paginationMixin ],
15741
props,
@@ -162,28 +46,31 @@ export default {
16246
}
16347
},
16448
methods: {
165-
setPage(e, num) {
166-
if (this.disabled) {
167-
e.preventDefault();
168-
e.stopPropagation();
169-
return;
170-
}
49+
// These methods are used by the render function
50+
onClick(num, evt) {
51+
// Handle edge cases where number of pages has changed (i.e. if perPage changes)
17152
if (num > this.numberOfPages) {
172-
this.currentPage = this.numberOfPages;
53+
num = this.numberOfPages;
17354
} else if (num < 1) {
174-
this.currentpage = 1;
175-
} else {
176-
this.currentPage = num;
55+
num = 1;
17756
}
57+
this.currentPage = num;
17858
this.$nextTick(() => {
17959
// Keep the current button focused if possible
180-
if (isVisible(e.target) && e.target.focus) {
181-
e.target.focus();
60+
const target = evt.target;
61+
if (isVisible(target) && this.$el.contains(target) && target.focus) {
62+
target.focus();
18263
} else {
18364
this.focusCurrent();
18465
}
18566
});
18667
this.$emit('change', this.currentPage);
68+
},
69+
makePage(pagenum) {
70+
return pagenum;
71+
},
72+
linkProps(pagenum) {
73+
return { href: '#' };
18774
}
18875
}
18976
};

0 commit comments

Comments
 (0)