Skip to content

Commit 3168e93

Browse files
authored
perf(dropdowns): convert templates to render functions (#1314)
* [dropdown mixin] prep for render functions * Create nav-item-dropdown.js * Update index.js * Delete nav-item-dropdown.vue * Update dropdown.js * Update dropdown.js
1 parent 88657fb commit 3168e93

File tree

5 files changed

+265
-112
lines changed

5 files changed

+265
-112
lines changed

src/components/dropdown/dropdown.js

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,120 @@
1-
import bDropdown from './dropdown.vue';
1+
import { idMixin, dropdownMixin } from '../../mixins';
2+
import bButton from '../button/button';
23

3-
export default bDropdown;
4+
export default {
5+
mixins: [idMixin, dropdownMixin],
6+
components: {bButton},
7+
render(h) {
8+
const t = this;
9+
let split = h(false);
10+
if (t.split) {
11+
split = h(
12+
'b-button',
13+
{
14+
ref: 'button',
15+
props: {
16+
disabled: t.disabled,
17+
variant: t.variant,
18+
size: t.size
19+
},
20+
attrs: {
21+
id: t.safeId('_BV_button_')
22+
},
23+
on: {
24+
click: t.click
25+
}
26+
},
27+
[ t.$slots['button-content'] || t.$slots.text || t.text ]
28+
);
29+
}
30+
const toggle = h(
31+
'b-button',
32+
{
33+
ref: 'toggle',
34+
class: {
35+
'dropdown-toggle': !t.noCaret || t.split,
36+
'dropdown-toggle-split': t.split
37+
},
38+
props: {
39+
variant: t.variant,
40+
size: t.size,
41+
disabled: t.disabled
42+
},
43+
attrs: {
44+
id: t.safeId('_BV_toggle_'),
45+
'aria-haspopup': 'true',
46+
'aria-expanded': t.visible ? 'true' : 'false'
47+
},
48+
on: {
49+
click: t.toggle, // click
50+
keydown: t.toggle // enter, space, down
51+
}
52+
},
53+
[ t.split
54+
? h('span', { class: [ 'sr-only' ] }, [t.toggleText])
55+
: (t.$slots['button-content'] || t.$slots.text || t.text)
56+
]
57+
);
58+
const menu = h(
59+
'div',
60+
{
61+
ref: 'menu',
62+
class: t.menuClasses,
63+
attrs: {
64+
role: t.role,
65+
'aria-labelledby': t.safeId(split ? '_BV_toggle_' : '_BV_button_')
66+
},
67+
on: {
68+
mouseover: t.onMouseOver,
69+
keydown: t.onKeydown // tab, up, down, esc
70+
}
71+
},
72+
[ this.$slots.default ]
73+
);
74+
return h('div', { attrs: { id: t.safeId() }, class: t.dropdownClasses }, [split, toggle, menu]);
75+
},
76+
props: {
77+
split: {
78+
type: Boolean,
79+
default: false
80+
},
81+
toggleText: {
82+
type: String,
83+
default: 'Toggle Dropdown'
84+
},
85+
size: {
86+
type: String,
87+
default: null
88+
},
89+
variant: {
90+
type: String,
91+
default: null
92+
},
93+
noCaret: {
94+
type: Boolean,
95+
default: false,
96+
},
97+
role: {
98+
type: String,
99+
default: 'menu'
100+
}
101+
},
102+
computed: {
103+
dropdownClasses() {
104+
return [
105+
'btn-group',
106+
'b-dropdown',
107+
'dropdown',
108+
this.dropup ? 'dropup' : '',
109+
this.visible ? 'show' : ''
110+
];
111+
},
112+
menuClasses() {
113+
return [
114+
'dropdown-menu',
115+
this.right ? 'dropdown-menu-right' : '',
116+
this.visible ? 'show' : ''
117+
];
118+
}
119+
}
120+
};

src/components/nav/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import bNav from './nav';
22
import bNavItem from './nav-item';
33
import bNavText from './nav-text';
44
import bNavForm from './nav-form';
5-
import bNavItemDropdown from './nav-item-dropdown.vue';
5+
import bNavItemDropdown from './nav-item-dropdown';
66
import dropdownPlugin from '../dropdown';
77
import { registerComponents, vueUse } from '../../utils';
88

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { idMixin, dropdownMixin } from '../../mixins';
2+
3+
export default {
4+
mixins: [idMixin, dropdownMixin],
5+
render(h) {
6+
const t = this;
7+
const button = h(
8+
'a',
9+
{
10+
class: t.toggleClasses,
11+
ref: 'toggle',
12+
attrs: {
13+
href: '#',
14+
id: t.safeId('_BV_button_'),
15+
disabled: t.disabled,
16+
'aria-haspopup': 'true',
17+
'aria-expanded': t.visible ? 'true' : 'false'
18+
},
19+
on: {
20+
click: t.toggle,
21+
keydown: t.toggle // space, enter, down
22+
}
23+
},
24+
[ t.$slots['button-content'] || t.$slots.text || h('span', { domProps: { innerHTML: t.text } }) ]
25+
);
26+
const menu = h(
27+
'div',
28+
{
29+
class: t.menuClasses,
30+
ref: 'menu',
31+
attrs: { 'aria-labelledby': t.safeId('_BV_button_') },
32+
on: {
33+
mouseover: t.onMouseOver,
34+
keydown: t.onKeydown // tab, up, down, esc
35+
}
36+
},
37+
[ this.$slots.default ]
38+
);
39+
return h('li', { attrs: { id: t.safeId() }, class: t.dropdownClasses }, [ button, menu ]);
40+
},
41+
computed: {
42+
isNav() {
43+
// Signal to dropdown mixin that we are in a navbar
44+
return true;
45+
},
46+
dropdownClasses() {
47+
return [
48+
'nav-item',
49+
'b-nav-dropdown',
50+
'dropdown',
51+
this.dropup ? 'dropup' : '',
52+
this.visible ? 'show' : ''
53+
];
54+
},
55+
toggleClasses() {
56+
return [
57+
'nav-link',
58+
this.noCaret ? '' : 'dropdown-toggle',
59+
this.disabled ? 'disabled' : ''
60+
];
61+
},
62+
menuClasses() {
63+
return [
64+
'dropdown-menu',
65+
this.right ? 'dropdown-menu-right': 'dropdown-menu-left',
66+
this.visible ? 'show' : ''
67+
];
68+
}
69+
},
70+
props: {
71+
noCaret: {
72+
type: Boolean,
73+
default: false
74+
},
75+
role: {
76+
type: String,
77+
default: 'menu'
78+
}
79+
}
80+
};

src/components/nav/nav-item-dropdown.vue

Lines changed: 0 additions & 80 deletions
This file was deleted.

0 commit comments

Comments
 (0)