feat(Tab): add scrollspy prop (#5273)
This commit is contained in:
@@ -170,6 +170,18 @@ In swipeable mode, you can switch tabs with swipe gestrue in the content
|
||||
</van-tabs>
|
||||
```
|
||||
|
||||
### Scrollspy
|
||||
|
||||
In scrollspy mode, the list of content will be tiled
|
||||
|
||||
```html
|
||||
<van-tabs v-model="active" scrollspy sticky>
|
||||
<van-tab v-for="index in 10" :title="'tab ' + index">
|
||||
content {{ index }}
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Tabs Props
|
||||
@@ -193,6 +205,7 @@ In swipeable mode, you can switch tabs with swipe gestrue in the content
|
||||
| sticky | Whether to use sticky mode | *boolean* | `false` | - |
|
||||
| swipeable | Whether to switch tabs with swipe gestrue in the content | *boolean* | `false` | - |
|
||||
| lazy-render | Whether to enable tab content lazy render | *boolean* | `true` | - |
|
||||
| scrollspy | Whether to use scrollspy mode | *boolean* | `false` | - |
|
||||
|
||||
### Tab Props
|
||||
|
||||
|
||||
@@ -174,6 +174,18 @@ export default {
|
||||
</van-tabs>
|
||||
```
|
||||
|
||||
### 滚动导航
|
||||
|
||||
通过`scrollspy`属性可以开启滚动导航模式,该模式下,内容将会平铺展示
|
||||
|
||||
```html
|
||||
<van-tabs v-model="active" scrollspy sticky>
|
||||
<van-tab v-for="index in 10" :title="'选项 ' + index">
|
||||
内容 {{ index }}
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Tabs Props
|
||||
@@ -197,6 +209,7 @@ export default {
|
||||
| sticky | 是否使用粘性定位布局 | *boolean* | `false` | - |
|
||||
| swipeable | 是否开启手势滑动切换 | *boolean* | `false` | - |
|
||||
| lazy-render | 是否开启标签页内容延迟渲染 | *boolean* | `true` | - |
|
||||
| scrollspy | 是否开启滚动导航 | *boolean* | `false` | - |
|
||||
|
||||
### Tab Props
|
||||
|
||||
|
||||
@@ -93,6 +93,14 @@
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="$t('title10')">
|
||||
<van-tabs scrollspy sticky>
|
||||
<van-tab :title="$t('tab') + index" v-for="index in 10" :key="index">
|
||||
{{ $t('content') }} {{ index }}
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</demo-block>
|
||||
</demo-section>
|
||||
</template>
|
||||
|
||||
@@ -109,6 +117,7 @@ export default {
|
||||
title7: '自定义标签',
|
||||
title8: '切换动画',
|
||||
title9: '滑动切换',
|
||||
title10: '滚动导航',
|
||||
disabled: ' 已被禁用',
|
||||
matchByName: '通过名称匹配'
|
||||
},
|
||||
@@ -123,6 +132,7 @@ export default {
|
||||
title7: 'Custom Tab',
|
||||
title8: 'Switch Animation',
|
||||
title9: 'Swipeable',
|
||||
title10: 'Scrollspy',
|
||||
disabled: ' is disabled',
|
||||
matchByName: 'Match By Name'
|
||||
}
|
||||
|
||||
+3
-2
@@ -46,7 +46,8 @@ export default createComponent({
|
||||
|
||||
render(h) {
|
||||
const { slots, isActive } = this;
|
||||
const shouldRender = this.inited || !this.parent.lazyRender;
|
||||
const shouldRender = this.inited || this.parent.scrollspy || !this.parent.lazyRender;
|
||||
const show = this.parent.scrollspy || isActive;
|
||||
const Content = shouldRender ? slots() : h();
|
||||
|
||||
if (this.parent.animated) {
|
||||
@@ -62,7 +63,7 @@ export default createComponent({
|
||||
}
|
||||
|
||||
return (
|
||||
<div vShow={isActive} role="tabpanel" class={bem('pane')}>
|
||||
<div vShow={show} role="tabpanel" class={bem('pane')}>
|
||||
{Content}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -275,5 +275,60 @@ exports[`renders demo correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="van-tabs van-tabs--line">
|
||||
<div>
|
||||
<div class="van-sticky">
|
||||
<div class="van-tabs__wrap van-tabs__wrap--scrollable van-hairline--top-bottom">
|
||||
<div role="tablist" class="van-tabs__nav van-tabs__nav--line">
|
||||
<div role="tab" aria-selected="true" class="van-tab van-tab--active van-ellipsis" style="flex-basis: 22%;"><span class="van-tab__text">标签 1<!----></span></div>
|
||||
<div role="tab" class="van-tab van-ellipsis" style="flex-basis: 22%;"><span class="van-tab__text">标签 2<!----></span></div>
|
||||
<div role="tab" class="van-tab van-ellipsis" style="flex-basis: 22%;"><span class="van-tab__text">标签 3<!----></span></div>
|
||||
<div role="tab" class="van-tab van-ellipsis" style="flex-basis: 22%;"><span class="van-tab__text">标签 4<!----></span></div>
|
||||
<div role="tab" class="van-tab van-ellipsis" style="flex-basis: 22%;"><span class="van-tab__text">标签 5<!----></span></div>
|
||||
<div role="tab" class="van-tab van-ellipsis" style="flex-basis: 22%;"><span class="van-tab__text">标签 6<!----></span></div>
|
||||
<div role="tab" class="van-tab van-ellipsis" style="flex-basis: 22%;"><span class="van-tab__text">标签 7<!----></span></div>
|
||||
<div role="tab" class="van-tab van-ellipsis" style="flex-basis: 22%;"><span class="van-tab__text">标签 8<!----></span></div>
|
||||
<div role="tab" class="van-tab van-ellipsis" style="flex-basis: 22%;"><span class="van-tab__text">标签 9<!----></span></div>
|
||||
<div role="tab" class="van-tab van-ellipsis" style="flex-basis: 22%;"><span class="van-tab__text">标签 10<!----></span></div>
|
||||
<div class="van-tabs__line" style="width: 0px; transform: translateX(0px) translateX(-50%);"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="van-tabs__content">
|
||||
<div role="tabpanel" class="van-tab__pane">
|
||||
内容 1
|
||||
</div>
|
||||
<div role="tabpanel" class="van-tab__pane">
|
||||
内容 2
|
||||
</div>
|
||||
<div role="tabpanel" class="van-tab__pane">
|
||||
内容 3
|
||||
</div>
|
||||
<div role="tabpanel" class="van-tab__pane">
|
||||
内容 4
|
||||
</div>
|
||||
<div role="tabpanel" class="van-tab__pane">
|
||||
内容 5
|
||||
</div>
|
||||
<div role="tabpanel" class="van-tab__pane">
|
||||
内容 6
|
||||
</div>
|
||||
<div role="tabpanel" class="van-tab__pane">
|
||||
内容 7
|
||||
</div>
|
||||
<div role="tabpanel" class="van-tab__pane">
|
||||
内容 8
|
||||
</div>
|
||||
<div role="tabpanel" class="van-tab__pane">
|
||||
内容 9
|
||||
</div>
|
||||
<div role="tabpanel" class="van-tab__pane">
|
||||
内容 10
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -223,6 +223,50 @@ exports[`render nav-left & nav-right slot 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`scrollspy 1`] = `
|
||||
<div class="van-tabs van-tabs--line">
|
||||
<div>
|
||||
<div class="van-sticky">
|
||||
<div class="van-tabs__wrap van-hairline--top-bottom">
|
||||
<div role="tablist" class="van-tabs__nav van-tabs__nav--line">
|
||||
<div role="tab" aria-selected="true" class="van-tab van-tab--active van-ellipsis"><span class="van-tab__text">title1<!----></span></div>
|
||||
<div role="tab" class="van-tab van-ellipsis"><span class="van-tab__text">title2<!----></span></div>
|
||||
<div role="tab" class="van-tab van-ellipsis"><span class="van-tab__text">title3<!----></span></div>
|
||||
<div class="van-tabs__line" style="width: 0px; transform: translateX(0px) translateX(-50%);"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="van-tabs__content">
|
||||
<div role="tabpanel" class="van-tab__pane">Text</div>
|
||||
<div role="tabpanel" class="van-tab__pane">Text</div>
|
||||
<div role="tabpanel" class="van-tab__pane">Text</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`scrollspy 2`] = `
|
||||
<div class="van-tabs van-tabs--line">
|
||||
<div>
|
||||
<div class="van-sticky">
|
||||
<div class="van-tabs__wrap van-hairline--top-bottom">
|
||||
<div role="tablist" class="van-tabs__nav van-tabs__nav--line">
|
||||
<div role="tab" class="van-tab van-ellipsis"><span class="van-tab__text">title1<!----></span></div>
|
||||
<div role="tab" class="van-tab van-ellipsis"><span class="van-tab__text">title2<!----></span></div>
|
||||
<div role="tab" class="van-tab van-tab--active van-ellipsis" aria-selected="true"><span class="van-tab__text">title3<!----></span></div>
|
||||
<div class="van-tabs__line" style="width: 0px; transform: translateX(0px) translateX(-50%); transition-duration: 0.3s;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="van-tabs__content">
|
||||
<div role="tabpanel" class="van-tab__pane">Text</div>
|
||||
<div role="tabpanel" class="van-tab__pane">Text</div>
|
||||
<div role="tabpanel" class="van-tab__pane">Text</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`swipe to switch tab 1`] = `
|
||||
<div class="van-tabs van-tabs--line">
|
||||
<div class="van-tabs__wrap van-hairline--top-bottom">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Vue from 'vue';
|
||||
import Tab from '..';
|
||||
import Tabs from '../../tabs';
|
||||
import { mount, later, triggerDrag } from '../../../test';
|
||||
import { mount, later, triggerDrag, mockScrollTop } from '../../../test';
|
||||
|
||||
Vue.use(Tab);
|
||||
Vue.use(Tabs);
|
||||
@@ -263,3 +263,33 @@ test('info prop', () => {
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('scrollspy', async () => {
|
||||
const onChange = jest.fn();
|
||||
window.scrollTo = jest.fn();
|
||||
|
||||
const wrapper = mount({
|
||||
template: `
|
||||
<van-tabs scrollspy sticky @change="onChange">
|
||||
<van-tab name="a" title="title1">Text</van-tab>
|
||||
<van-tab name="b" title="title2">Text</van-tab>
|
||||
<van-tab name="c" title="title3">Text</van-tab>
|
||||
</van-tabs>
|
||||
`,
|
||||
methods: {
|
||||
onChange
|
||||
}
|
||||
});
|
||||
|
||||
await later();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
const tabs = wrapper.findAll('.van-tab');
|
||||
tabs.at(2).trigger('click');
|
||||
expect(onChange).toHaveBeenCalledWith('c', 'title3');
|
||||
|
||||
await later();
|
||||
mockScrollTop(100);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(onChange).toHaveBeenCalledWith('c', 'title3');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user