[new feature] Tabs: add animated props to change tabs with animation (#2126)

This commit is contained in:
张敏 2018-11-23 19:51:47 +08:00 committed by neverland
parent 8042e37829
commit d84b13a6cc
15 changed files with 2097 additions and 268 deletions

View File

@ -7,7 +7,11 @@
left-arrow left-arrow
@click-left="onBack" @click-left="onBack"
> >
<a slot="right" :href="demoLink" target="_blank"> <a
slot="right"
:href="demoLink"
target="_blank"
>
<van-icon name="edit" /> <van-icon name="edit" />
</a> </a>
</van-nav-bar> </van-nav-bar>

View File

@ -5,11 +5,24 @@
<span>Vant</span> <span>Vant</span>
</h1> </h1>
<div class="mobile-switch-lang"> <div class="mobile-switch-lang">
<span :class="{ active: $vantLang === 'en-US' }" @click="switchLang('en-US')">EN</span> <span
<span :class="{ active: $vantLang === 'zh-CN' }" @click="switchLang('zh-CN')">中文</span> :class="{ active: $vantLang === 'en-US' }"
@click="switchLang('en-US')"
>
EN
</span>
<span
:class="{ active: $vantLang === 'zh-CN' }"
@click="switchLang('zh-CN')"
>
中文
</span>
</div> </div>
<h2 class="zanui-desc">{{ description }}</h2> <h2 class="zanui-desc">{{ description }}</h2>
<template v-for="item in navList" v-if="item.showInMobile"> <template
v-for="item in navList"
v-if="item.showInMobile"
>
<mobile-nav <mobile-nav
v-for="(group, index) in item.groups" v-for="(group, index) in item.groups"
:group="group" :group="group"
@ -26,16 +39,16 @@ import MobileNav from './MobileNav';
import { setLang } from '../utils/lang'; import { setLang } from '../utils/lang';
export default { export default {
components: {
MobileNav
},
data() { data() {
return { return {
docConfig docConfig
}; };
}, },
components: {
MobileNav
},
computed: { computed: {
navList() { navList() {
return this.docConfig[this.$vantLang].nav || []; return this.docConfig[this.$vantLang].nav || [];

View File

@ -8,8 +8,16 @@
v-for="(demo, index) in demos" v-for="(demo, index) in demos"
> >
<h4>{{ demo.title }}</h4> <h4>{{ demo.title }}</h4>
<a :href="demo.source" target="_blank">{{ $t('source') }}</a> <a
<img :src="demo.preview" @click="onChangeDemo(demo, index)" > :href="demo.source"
target="_blank"
>
{{ $t('source') }}
</a>
<img
:src="demo.preview"
@click="onChangeDemo(demo, index)"
>
</div> </div>
</div> </div>
</section> </section>

View File

@ -1,6 +1,13 @@
<template> <template>
<van-collapse v-model="active" class="mobile-nav"> <van-collapse
<van-collapse-item :title="group.groupName" :name="group.groupName" class="mobile-nav__item"> v-model="active"
class="mobile-nav"
>
<van-collapse-item
class="mobile-nav__item"
:title="group.groupName"
:name="group.groupName"
>
<van-cell <van-cell
v-if="!navItem.disabled" v-if="!navItem.disabled"
v-for="(navItem, index) in group.list" v-for="(navItem, index) in group.list"

View File

@ -33,7 +33,7 @@ if (process.env.NODE_ENV !== 'production') {
} }
new Vue({ // eslint-disable-line new Vue({ // eslint-disable-line
el: '#app',
render: h => h(App), render: h => h(App),
router, router
el: '#app'
}); });

View File

@ -91,6 +91,21 @@
</demo-block> </demo-block>
<demo-block :title="$t('title8')"> <demo-block :title="$t('title8')">
<van-tabs
:active="active"
animated
>
<van-tab
:title="$t('tab') + index"
v-for="index in tabs"
:key="index"
>
{{ $t('content') }} {{ index }}
</van-tab>
</van-tabs>
</demo-block>
<demo-block :title="$t('title9')">
<van-tabs <van-tabs
:active="active" :active="active"
swipeable swipeable
@ -118,7 +133,8 @@ export default {
title5: '点击事件', title5: '点击事件',
title6: '粘性布局', title6: '粘性布局',
title7: '自定义标签', title7: '自定义标签',
title8: '滑动切换', title8: '切换动画',
title9: '滑动切换',
disabled: ' 已被禁用' disabled: ' 已被禁用'
}, },
'en-US': { 'en-US': {
@ -130,7 +146,8 @@ export default {
title5: 'Click Event', title5: 'Click Event',
title6: 'Sticky', title6: 'Sticky',
title7: 'Custom Tab', title7: 'Custom Tab',
title8: 'Swipeable', title8: 'Switch Animation',
title9: 'Swipeable',
disabled: ' is disabled' disabled: ' is disabled'
} }
}, },

View File

@ -122,6 +122,18 @@ Use title slot to custom tab title
</van-tabs> </van-tabs>
``` ```
#### Switch Animation
Use `animated` props to change tabs with animation
```html
<van-tabs v-model="active" animated>
<van-tab v-for="index in 4" :title="'tab ' + index">
content {{ index }}
</van-tab>
</van-tabs>
```
#### Swipeable #### Swipeable
In swipeable mode, you can switch tabs with swipe gestrue in the content In swipeable mode, you can switch tabs with swipe gestrue in the content
@ -141,12 +153,13 @@ In swipeable mode, you can switch tabs with swipe gestrue in the content
| v-model | Index of active tab | `String` `Number` | `0` | | v-model | Index of active tab | `String` `Number` | `0` |
| color | Tab color | `String` | `#f44` | | color | Tab color | `String` | `#f44` |
| type | Can be set to `line` `card` | `String` | `line` | | type | Can be set to `line` `card` | `String` | `line` |
| duration | Toggle tab's animation time | `Number` | `0.2` | - | | duration | Toggle tab's animation time | `Number` | `0.4` | - |
| line-width | Width of tab line (px) | `Number` | Width of active tab | | line-width | Width of tab line (px) | `Number` | Width of active tab |
| swipe-threshold | Set swipe tabs threshold | `Number` | `4` | - | | swipe-threshold | Set swipe tabs threshold | `Number` | `4` | - |
| sticky | Whether to use sticky mode | `Boolean` | `false` | | sticky | Whether to use sticky mode | `Boolean` | `false` |
| offset-top | Offset top when use sticky mode | `Number` | `0` | | offset-top | Offset top when use sticky mode | `Number` | `0` |
| swipeable | Whether to switch tabs with swipe gestrue in the content | `Boolean` | `false` | | swipeable | Whether to switch tabs with swipe gestrue in the content | `Boolean` | `false` |
| animated | Whether to change tabs with animation | `false` | - |
### Tab API ### Tab API

View File

@ -1,7 +1,8 @@
<template> <template>
<div <div
:class="b('pane')" :class="b('pane', { float: parent.animated })"
v-show="isSelected" v-show="parent.animated || isSelected"
:style="paneStyle"
> >
<slot v-if="inited" /> <slot v-if="inited" />
<div <div
@ -29,7 +30,8 @@ export default create({
data() { data() {
return { return {
inited: false inited: false,
paneStyle: {}
}; };
}, },
@ -48,6 +50,12 @@ export default create({
this.inited = this.inited || this.isSelected; this.inited = this.inited || this.isSelected;
}, },
'parent.computedWidth'(width) {
this.paneStyle = {
width: `${width}px`
};
},
title() { title() {
this.parent.setLine(); this.parent.setLine();
} }

View File

@ -10,6 +10,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tabs__track" style="display:none;">
<div class="van-tab__pane" style="display:none;"> <div class="van-tab__pane" style="display:none;">
<!----> <!---->
<!----> <!---->
@ -29,6 +30,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
</div> </div>
</div>
<div> <div>
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
@ -37,6 +39,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tabs__track" style="display:none;">
<div class="van-tab__pane" style="display:none;"> <div class="van-tab__pane" style="display:none;">
<!----> <!---->
<!----> <!---->
@ -72,6 +75,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
</div> </div>
</div>
<div> <div>
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
@ -80,6 +84,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tabs__track" style="display:none;">
<div class="van-tab__pane" style="display:none;"> <div class="van-tab__pane" style="display:none;">
<!----> <!---->
<!----> <!---->
@ -95,6 +100,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
</div> </div>
</div>
<div> <div>
<div class="van-tabs van-tabs--card"> <div class="van-tabs van-tabs--card">
<div class="van-tabs__wrap"> <div class="van-tabs__wrap">
@ -103,6 +109,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tabs__track" style="display:none;">
<div class="van-tab__pane" style="display:none;"> <div class="van-tab__pane" style="display:none;">
<!----> <!---->
<!----> <!---->
@ -118,6 +125,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
</div> </div>
</div>
<div> <div>
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
@ -126,6 +134,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tabs__track" style="display:none;">
<div class="van-tab__pane" style="display:none;"> <div class="van-tab__pane" style="display:none;">
<!----> <!---->
<!----> <!---->
@ -137,6 +146,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
</div> </div>
</div>
<div> <div>
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
@ -145,6 +155,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tabs__track" style="display:none;">
<div class="van-tab__pane" style="display:none;"> <div class="van-tab__pane" style="display:none;">
<!----> <!---->
<!----> <!---->
@ -164,6 +175,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
</div> </div>
</div>
<div> <div>
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
@ -172,6 +184,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tabs__track" style="display:none;">
<div class="van-tab__pane" style="display:none;"> <div class="van-tab__pane" style="display:none;">
<!----> <!---->
<div> <div>
@ -195,6 +208,7 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
</div> </div>
</div>
<div> <div>
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
@ -203,6 +217,36 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tabs__track" style="width:0px;transition-duration:0.4s;transform:translateX(0px);display:none;">
<div class="van-tab__pane van-tab__pane--float">
<!---->
<!---->
</div>
<div class="van-tab__pane van-tab__pane--float">
<!---->
<!---->
</div>
<div class="van-tab__pane van-tab__pane--float">
<!---->
<!---->
</div>
<div class="van-tab__pane van-tab__pane--float">
<!---->
<!---->
</div>
</div>
</div>
</div>
</div>
<div>
<div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom">
<div class="van-tabs__nav van-tabs__nav--line" style="border-color:undefined;">
<div class="van-tabs__line"></div>
</div>
</div>
<div class="van-tabs__content">
<div class="van-tabs__track" style="display:none;">
<div class="van-tab__pane" style="display:none;"> <div class="van-tab__pane" style="display:none;">
<!----> <!---->
<!----> <!---->
@ -222,5 +266,6 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
</div> </div>
</div>
</div> </div>
`; `;

View File

@ -1,15 +1,41 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`click to switch tab 1`] = ` exports[`change tabs data 1`] = `
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
<div class="van-tabs__nav van-tabs__nav--line"> <div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
<div class="van-tabs__line" style="width: 0px;"></div> <div class="van-tabs__line"></div>
</div>
</div>
<div class="van-tabs__content">
<div class="van-tabs__track" style="display: none;">
<div class="van-tab__pane" style="display: none;">
<!---->
<!---->
</div>
<div class="van-tab__pane" style="display: none;">
<!---->
<div><span>title2</span></div>
</div>
<div class="van-tab__pane" style="display: none;">
<!---->
<!---->
</div>
</div>
</div>
</div>
`;
exports[`change tabs data 2`] = `
<div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom">
<div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
<div class="van-tabs__line"></div>
<div class="van-tab van-tab--active"><span class="van-ellipsis"> <div class="van-tab van-tab--active"><span class="van-ellipsis">
title1 title1
</span></div> </span></div>
<div class="van-tab"><span class="van-ellipsis"> <div class="van-tab"><span class="van-ellipsis">
title2
</span></div> </span></div>
<div class="van-tab van-tab--disabled"><span class="van-ellipsis"> <div class="van-tab van-tab--disabled"><span class="van-ellipsis">
title3 title3
@ -17,16 +43,52 @@ exports[`click to switch tab 1`] = `
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tab__pane" style="">Text <div class="van-tabs__track" style="display: none;">
<!----> <div class="van-tab__pane" style="">
</div>
<div class="van-tab__pane" style="display: none;">
<!----> <!---->
<!----> <!---->
</div> </div>
<div class="van-tab__pane" style="display: none;"> <div class="van-tab__pane" style="display: none;">
<!----> <!---->
<div><span>title2</span></div>
</div>
<div class="van-tab__pane" style="display: none;">
<!----> <!---->
<!---->
</div>
</div>
</div>
</div>
`;
exports[`click to switch tab 1`] = `
<div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom">
<div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
<div class="van-tabs__line" style="width: 2px; background-color: rgb(255, 68, 68);"></div>
<div class="van-tab van-tab--active"><span class="van-ellipsis">
title1
</span></div>
<div class="van-tab">
<div><span>title2</span></div>
</div>
<div class="van-tab van-tab--disabled"><span class="van-ellipsis">
title3
</span></div>
</div>
</div>
<div class="van-tabs__content">
<div class="van-tabs__track" style="display: none;">
<div class="van-tab__pane" style="width: 0px;">Text
<!---->
</div>
<div class="van-tab__pane" style="display: none; width: 0px;">
<!---->
</div>
<div class="van-tab__pane" style="display: none; width: 0px;">
<!---->
<!---->
</div>
</div> </div>
</div> </div>
</div> </div>
@ -35,29 +97,31 @@ exports[`click to switch tab 1`] = `
exports[`click to switch tab 2`] = ` exports[`click to switch tab 2`] = `
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
<div class="van-tabs__nav van-tabs__nav--line"> <div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
<div class="van-tabs__line" style="width: 0px;"></div> <div class="van-tabs__line" style="width: 2px; background-color: rgb(255, 68, 68);"></div>
<div class="van-tab"><span class="van-ellipsis"> <div class="van-tab"><span class="van-ellipsis">
title1 title1
</span></div> </span></div>
<div class="van-tab van-tab--active"><span class="van-ellipsis"> <div class="van-tab van-tab--active">
title2 <div><span>title2</span></div>
</span></div> </div>
<div class="van-tab van-tab--disabled"><span class="van-ellipsis"> <div class="van-tab van-tab--disabled"><span class="van-ellipsis">
title3 title3
</span></div> </span></div>
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tab__pane" style="display: none;">Text <div class="van-tabs__track" style="display: none;">
<div class="van-tab__pane" style="width: 0px; display: none;">Text
<!----> <!---->
</div> </div>
<div class="van-tab__pane" style="">Text <div class="van-tab__pane" style="width: 0px;">
Text
</div>
<div class="van-tab__pane" style="display: none; width: 0px;">
<!---->
<!----> <!---->
</div> </div>
<div class="van-tab__pane" style="display: none;">
<!---->
<!---->
</div> </div>
</div> </div>
</div> </div>
@ -66,30 +130,31 @@ exports[`click to switch tab 2`] = `
exports[`swipe to switch tab 1`] = ` exports[`swipe to switch tab 1`] = `
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
<div class="van-tabs__nav van-tabs__nav--line"> <div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
<div class="van-tabs__line" style="width: 0px;"></div> <div class="van-tabs__line" style="width: 2px; background-color: rgb(255, 68, 68);"></div>
<div class="van-tab van-tab--active"><span class="van-ellipsis"> <div class="van-tab van-tab--active"><span class="van-ellipsis">
title1 title1
</span></div> </span></div>
<div class="van-tab"><span class="van-ellipsis"> <div class="van-tab">
title2 <div><span>title2</span></div>
</span></div> </div>
<div class="van-tab van-tab--disabled"><span class="van-ellipsis"> <div class="van-tab van-tab--disabled"><span class="van-ellipsis">
title3 title3
</span></div> </span></div>
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tab__pane" style="">Text <div class="van-tabs__track" style="display: none;">
<div class="van-tab__pane" style="width: 0px;">Text
<!----> <!---->
</div> </div>
<div class="van-tab__pane" style="display: none;"> <div class="van-tab__pane" style="display: none; width: 0px;">
<!---->
</div>
<div class="van-tab__pane" style="display: none; width: 0px;">
<!----> <!---->
<!----> <!---->
</div> </div>
<div class="van-tab__pane" style="display: none;">
<!---->
<!---->
</div> </div>
</div> </div>
</div> </div>
@ -98,29 +163,31 @@ exports[`swipe to switch tab 1`] = `
exports[`swipe to switch tab 2`] = ` exports[`swipe to switch tab 2`] = `
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
<div class="van-tabs__nav van-tabs__nav--line"> <div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
<div class="van-tabs__line" style="width: 0px;"></div> <div class="van-tabs__line" style="width: 2px; background-color: rgb(255, 68, 68);"></div>
<div class="van-tab"><span class="van-ellipsis"> <div class="van-tab"><span class="van-ellipsis">
title1 title1
</span></div> </span></div>
<div class="van-tab van-tab--active"><span class="van-ellipsis"> <div class="van-tab van-tab--active">
title2 <div><span>title2</span></div>
</span></div> </div>
<div class="van-tab van-tab--disabled"><span class="van-ellipsis"> <div class="van-tab van-tab--disabled"><span class="van-ellipsis">
title3 title3
</span></div> </span></div>
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tab__pane" style="display: none;">Text <div class="van-tabs__track" style="display: none;">
<div class="van-tab__pane" style="width: 0px; display: none;">Text
<!----> <!---->
</div> </div>
<div class="van-tab__pane" style="">Text <div class="van-tab__pane" style="width: 0px;">
Text
</div>
<div class="van-tab__pane" style="display: none; width: 0px;">
<!---->
<!----> <!---->
</div> </div>
<div class="van-tab__pane" style="display: none;">
<!---->
<!---->
</div> </div>
</div> </div>
</div> </div>
@ -129,29 +196,31 @@ exports[`swipe to switch tab 2`] = `
exports[`swipe to switch tab 3`] = ` exports[`swipe to switch tab 3`] = `
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
<div class="van-tabs__nav van-tabs__nav--line"> <div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
<div class="van-tabs__line" style="width: 0px;"></div> <div class="van-tabs__line" style="width: 2px; background-color: rgb(255, 68, 68);"></div>
<div class="van-tab"><span class="van-ellipsis"> <div class="van-tab"><span class="van-ellipsis">
title1 title1
</span></div> </span></div>
<div class="van-tab van-tab--active"><span class="van-ellipsis"> <div class="van-tab van-tab--active">
title2 <div><span>title2</span></div>
</span></div> </div>
<div class="van-tab van-tab--disabled"><span class="van-ellipsis"> <div class="van-tab van-tab--disabled"><span class="van-ellipsis">
title3 title3
</span></div> </span></div>
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tab__pane" style="display: none;">Text <div class="van-tabs__track" style="display: none;">
<div class="van-tab__pane" style="width: 0px; display: none;">Text
<!----> <!---->
</div> </div>
<div class="van-tab__pane" style="">Text <div class="van-tab__pane" style="width: 0px;">
Text
</div>
<div class="van-tab__pane" style="display: none; width: 0px;">
<!---->
<!----> <!---->
</div> </div>
<div class="van-tab__pane" style="display: none;">
<!---->
<!---->
</div> </div>
</div> </div>
</div> </div>
@ -160,29 +229,31 @@ exports[`swipe to switch tab 3`] = `
exports[`swipe to switch tab 4`] = ` exports[`swipe to switch tab 4`] = `
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
<div class="van-tabs__nav van-tabs__nav--line"> <div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
<div class="van-tabs__line" style="width: 0px;"></div> <div class="van-tabs__line" style="width: 2px; background-color: rgb(255, 68, 68);"></div>
<div class="van-tab van-tab--active"><span class="van-ellipsis"> <div class="van-tab van-tab--active"><span class="van-ellipsis">
title1 title1
</span></div> </span></div>
<div class="van-tab"><span class="van-ellipsis"> <div class="van-tab">
title2 <div><span>title2</span></div>
</span></div> </div>
<div class="van-tab van-tab--disabled"><span class="van-ellipsis"> <div class="van-tab van-tab--disabled"><span class="van-ellipsis">
title3 title3
</span></div> </span></div>
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tab__pane" style="">Text <div class="van-tabs__track" style="display: none;">
<div class="van-tab__pane" style="width: 0px;">Text
<!----> <!---->
</div> </div>
<div class="van-tab__pane" style="display: none;">Text <div class="van-tab__pane" style="width: 0px; display: none;">
Text
</div>
<div class="van-tab__pane" style="display: none; width: 0px;">
<!---->
<!----> <!---->
</div> </div>
<div class="van-tab__pane" style="display: none;">
<!---->
<!---->
</div> </div>
</div> </div>
</div> </div>

View File

@ -5,9 +5,18 @@ import { mount, later, triggerDrag } from '../../../test/utils';
function createWrapper(options) { function createWrapper(options) {
return mount({ return mount({
template: ` template: `
<tabs @change="onChange" swipeable> <tabs @change="onChange"
<tab title="title1">Text</tab> :color="color"
<tab title="title2">Text</tab> :type="type"
:swipeable="swipeable"
:sticky="sticky"
:line-width="lineWidth"
>
<tab :title="title1">Text</tab>
<tab>
<span slot="title">title2</span>
Text
</tab>
<tab title="title3" disabled>Text</tab> <tab title="title3" disabled>Text</tab>
</tabs> </tabs>
`, `,
@ -15,6 +24,16 @@ function createWrapper(options) {
Tab, Tab,
Tabs Tabs
}, },
data() {
return {
title1: 'title1',
color: '#f44',
type: 'line',
swipeable: true,
sticky: true,
lineWidth: 2
};
},
...options ...options
}); });
} }
@ -61,3 +80,18 @@ test('swipe to switch tab', async() => {
await later(); await later();
wrapper.destroy(); wrapper.destroy();
}); });
test('change tabs data', async() => {
const wrapper = createWrapper();
expect(wrapper).toMatchSnapshot();
wrapper.setData({
swipeable: false,
sticky: false,
type: 'card',
color: 'blue',
title1: 'new title1'
});
expect(wrapper).toMatchSnapshot();
});

View File

@ -126,6 +126,18 @@ export default {
</van-tabs> </van-tabs>
``` ```
#### 切换动画
通过`animated`属性可以开启切换tab时的动画
```html
<van-tabs v-model="active" animated>
<van-tab v-for="index in 4" :title="'选项 ' + index">
内容 {{ index }}
</van-tab>
</van-tabs>
```
#### 滑动切换 #### 滑动切换
通过`swipeable`属性可以开启滑动切换tab 通过`swipeable`属性可以开启滑动切换tab
@ -145,12 +157,13 @@ export default {
| v-model | 当前标签的索引 | `String` `Number` | `0` | 1.0.6 | | v-model | 当前标签的索引 | `String` `Number` | `0` | 1.0.6 |
| color | 标签颜色 | `String` | `#f44` | 1.2.0 | | color | 标签颜色 | `String` | `#f44` | 1.2.0 |
| type | 样式类型,可选值为`card` | `String` | `line` | - | | type | 样式类型,可选值为`card` | `String` | `line` | - |
| duration | 动画时间,单位秒 | `Number` | `0.2` | - | | duration | 动画时间,单位秒 | `Number` | `0.4` | - |
| line-width | 底部条宽度,单位 px | `Number` | - | 1.1.1 | | line-width | 底部条宽度,单位 px | `Number` | - | 1.1.1 |
| swipeable | 是否开启手势滑动切换 | `Boolean` | `false` | 1.0.0 | | swipeable | 是否开启手势滑动切换 | `Boolean` | `false` | 1.0.0 |
| sticky | 是否使用粘性定位布局 | `Boolean` | `false` | - | | sticky | 是否使用粘性定位布局 | `Boolean` | `false` | - |
| offset-top | 粘性定位布局下与顶部的最小距离,单位 px | `Number` | `0` | 1.1.15 | | offset-top | 粘性定位布局下与顶部的最小距离,单位 px | `Number` | `0` | 1.1.15 |
| swipe-threshold | 滚动阈值,标签数量超过多少个可滚动 | `Number` | `4` | - | | swipe-threshold | 滚动阈值,标签数量超过多少个可滚动 | `Number` | `4` | - |
| animated | 是否使用动画切换 Tabs | `false` | - | 1.4.5 |
### Tab API ### Tab API

View File

@ -114,6 +114,10 @@
background-color: @red; background-color: @red;
} }
&__content {
overflow: hidden;
}
&--line { &--line {
padding-top: @tabs-line-height; padding-top: @tabs-line-height;
@ -129,4 +133,12 @@
height: @tabs-card-height; height: @tabs-card-height;
} }
} }
.van-tab__pane {
box-sizing: border-box;
&--float {
float: left;
}
}
} }

View File

@ -41,10 +41,16 @@
<div <div
ref="content" ref="content"
:class="b('content')" :class="b('content')"
>
<div
v-show="computedWidth !== 0"
:class="b('track')"
:style="trackStyle"
> >
<slot /> <slot />
</div> </div>
</div> </div>
</div>
</template> </template>
<script> <script>
@ -78,7 +84,7 @@ export default create({
}, },
duration: { duration: {
type: Number, type: Number,
default: 0.2 default: 0.4
}, },
swipeThreshold: { swipeThreshold: {
type: Number, type: Number,
@ -87,7 +93,8 @@ export default create({
offsetTop: { offsetTop: {
type: Number, type: Number,
default: 0 default: 0
} },
animated: Boolean
}, },
data() { data() {
@ -100,7 +107,8 @@ export default create({
resize: false, resize: false,
sticky: false, sticky: false,
swipeable: false swipeable: false
} },
computedWidth: 0
}; };
}, },
@ -131,6 +139,23 @@ export default create({
return { return {
borderColor: this.color borderColor: this.color
}; };
},
trackStyle() {
const {
curActive,
computedWidth = 0,
tabs,
animated
} = this;
if (!animated) return {};
const offset = -1 * computedWidth * curActive;
return {
width: `${computedWidth * tabs.length}px`,
transitionDuration: `${this.duration}s`,
transform: `translateX(${offset}px)`
};
} }
}, },
@ -173,6 +198,7 @@ export default create({
mounted() { mounted() {
this.correctActive(this.active); this.correctActive(this.active);
this.setLine(); this.setLine();
this.setWidth();
this.$nextTick(() => { this.$nextTick(() => {
this.handlers(true); this.handlers(true);
@ -196,6 +222,13 @@ export default create({
}, },
methods: { methods: {
setWidth() {
if (this.$el) {
const rect = this.$el.getBoundingClientRect() || {};
this.computedWidth = rect.width;
}
},
// whether to bind sticky listener // whether to bind sticky listener
handlers(bind) { handlers(bind) {
const { events } = this; const { events } = this;
@ -267,11 +300,13 @@ export default create({
// update nav bar style // update nav bar style
setLine() { setLine() {
this.$nextTick(() => { this.$nextTick(() => {
if (!this.$refs.tabs || this.type !== 'line') { const { tabs } = this.$refs;
if (!tabs || this.type !== 'line') {
return; return;
} }
const tab = this.$refs.tabs[this.curActive]; const tab = tabs[this.curActive];
const width = this.isDef(this.lineWidth) ? this.lineWidth : (tab.offsetWidth / 2); const width = this.isDef(this.lineWidth) ? this.lineWidth : (tab.offsetWidth / 2);
const left = tab.offsetLeft + (tab.offsetWidth - width) / 2; const left = tab.offsetLeft + (tab.offsetWidth - width) / 2;
@ -329,11 +364,13 @@ export default create({
// scroll active tab into view // scroll active tab into view
scrollIntoView(immediate) { scrollIntoView(immediate) {
if (!this.scrollable || !this.$refs.tabs) { const { tabs } = this.$refs;
if (!this.scrollable || !tabs) {
return; return;
} }
const tab = this.$refs.tabs[this.curActive]; const tab = tabs[this.curActive];
const { nav } = this.$refs; const { nav } = this.$refs;
const { scrollLeft, offsetWidth: navWidth } = nav; const { scrollLeft, offsetWidth: navWidth } = nav;
const { offsetLeft, offsetWidth: tabWidth } = tab; const { offsetLeft, offsetWidth: tabWidth } = tab;

1547
yarn.lock

File diff suppressed because it is too large Load Diff