[Improvement] Tab: support v-model bind active tab (#879)

This commit is contained in:
neverland 2018-04-16 19:11:48 +08:00 committed by GitHub
parent 2ce0803ffe
commit ed1bff1052
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 29 additions and 18 deletions

View File

@ -1,7 +1,7 @@
<template> <template>
<demo-section> <demo-section>
<demo-block :title="$t('basicUsage')"> <demo-block :title="$t('basicUsage')">
<van-tabs :active="active"> <van-tabs v-model="active">
<van-tab :title="$t('tab') + index" v-for="index in tabs" :key="index"> <van-tab :title="$t('tab') + index" v-for="index in tabs" :key="index">
{{ $t('content') }} {{ index }} {{ $t('content') }} {{ index }}
</van-tab> </van-tab>

View File

@ -11,10 +11,10 @@ Vue.use(Tab).use(Tabs);
#### Basic Usage #### Basic Usage
By default, the first tab is actived. You can set `active` attribute on `van-tabs` to active specified tab. The first tab is actived by default, you can set `v-model` to active specified tab.
```html ```html
<van-tabs :active="active"> <van-tabs v-model="active">
<van-tab v-for="index in 4" :title="'tab' + index"> <van-tab v-for="index in 4" :title="'tab' + index">
content of tab {{ index }} content of tab {{ index }}
</van-tab> </van-tab>
@ -101,7 +101,7 @@ export default {
In sticky mode, the tab will be fixed to top when scroll to top In sticky mode, the tab will be fixed to top when scroll to top
```html ```html
<van-tabs :active="active" sticky> <van-tabs v-model="active" sticky>
<van-tab v-for="index in 4" :title="'tab ' + index"> <van-tab v-for="index in 4" :title="'tab ' + index">
content {{ index }} content {{ index }}
</van-tab> </van-tab>
@ -112,7 +112,7 @@ In sticky mode, the tab will be fixed to top when scroll to top
Use title slot to custom tab title Use title slot to custom tab title
```html ```html
<van-tabs :active="active"> <van-tabs v-model="active">
<van-tab v-for="index in 2"> <van-tab v-for="index in 2">
<div slot="title"> <div slot="title">
<van-icon name="more-o" />tab <van-icon name="more-o" />tab
@ -127,7 +127,7 @@ Use title slot to custom tab title
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
```html ```html
<van-tabs :active="active" swipeable> <van-tabs v-model="active" swipeable>
<van-tab v-for="index in 4" :title="'tab ' + index"> <van-tab v-for="index in 4" :title="'tab ' + index">
content {{ index }} content {{ index }}
</van-tab> </van-tab>
@ -138,8 +138,8 @@ In swipeable mode, you can switch tabs with swipe gestrue in the content
| Attribute | Description | Type | Default | Accepted Values | | Attribute | Description | Type | Default | Accepted Values |
|-----------|-----------|-----------|-------------|-------------| |-----------|-----------|-----------|-------------|-------------|
| v-model | Index of active tab | `String` `Number` | `0` | - |
| type | There are two style tabs, set this attribute to change tab style | `String` | `line` | `card` | | type | There are two style tabs, set this attribute to change tab style | `String` | `line` | `card` |
| active | Index of active tab | `String` `Number` | `0` | - |
| duration | Toggle tab's animation time | `Number` | `0.2` | - | - | | duration | Toggle tab's animation time | `Number` | `0.2` | - | - |
| 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` | - |

View File

@ -11,10 +11,10 @@ Vue.use(Tab).use(Tabs);
#### 基础用法 #### 基础用法
默认情况下启用第一个 tab可以通过`active`属性激活对应特定索引的 tab 默认情况下启用第一个 tab可以通过`v-model`绑定当前激活的标签索引
```html ```html
<van-tabs :active="active"> <van-tabs v-model="active">
<van-tab v-for="index in 4" :title="'选项 ' + index"> <van-tab v-for="index in 4" :title="'选项 ' + index">
内容 {{ index }} 内容 {{ index }}
</van-tab> </van-tab>
@ -103,7 +103,7 @@ export default {
通过`sticky`属性可以开启粘性布局,粘性布局下,当 Tab 滚动到顶部时会自动吸顶 通过`sticky`属性可以开启粘性布局,粘性布局下,当 Tab 滚动到顶部时会自动吸顶
```html ```html
<van-tabs :active="active" sticky> <van-tabs v-model="active" sticky>
<van-tab v-for="index in 4" :title="'选项 ' + index"> <van-tab v-for="index in 4" :title="'选项 ' + index">
内容 {{ index }} 内容 {{ index }}
</van-tab> </van-tab>
@ -114,7 +114,7 @@ export default {
通过 title slot 可以自定义标签内容 通过 title slot 可以自定义标签内容
```html ```html
<van-tabs :active="active"> <van-tabs v-model="active">
<van-tab v-for="index in 2"> <van-tab v-for="index in 2">
<div slot="title"> <div slot="title">
<van-icon name="more-o" />选项 <van-icon name="more-o" />选项
@ -129,7 +129,7 @@ export default {
通过`swipeable`属性可以开启滑动切换tab 通过`swipeable`属性可以开启滑动切换tab
```html ```html
<van-tabs :active="active" swipeable> <van-tabs v-model="active" swipeable>
<van-tab v-for="index in 4" :title="'选项 ' + index"> <van-tab v-for="index in 4" :title="'选项 ' + index">
内容 {{ index }} 内容 {{ index }}
</van-tab> </van-tab>
@ -140,8 +140,8 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | 可选 | | 参数 | 说明 | 类型 | 默认值 | 可选 |
|-----------|-----------|-----------|-------------|-------------| |-----------|-----------|-----------|-------------|-------------|
| v-model | 当前激活的 tab | `String` `Number` | `0` | - |
| type | Tab 样式类型 | `String` | `line` | `card` | | type | Tab 样式类型 | `String` | `line` | `card` |
| active | 默认激活的 tab | `String` `Number` | `0` | - |
| duration | 切换 tab 的动画时间 | `Number` | `0.2` | - | | duration | 切换 tab 的动画时间 | `Number` | `0.2` | - |
| swipe-threshold | 滚动阀值,设置 Tab 超过多少个可滚动 | `Number` | `4` | - | | swipe-threshold | 滚动阀值,设置 Tab 超过多少个可滚动 | `Number` | `4` | - |
| sticky | 是否使用粘性定位布局 | `Boolean` | `false` | - | | sticky | 是否使用粘性定位布局 | `Boolean` | `false` | - |

View File

@ -49,6 +49,10 @@ export default create({
VanNode VanNode
}, },
model: {
prop: 'active'
},
props: { props: {
sticky: Boolean, sticky: Boolean,
active: { active: {
@ -88,7 +92,9 @@ export default create({
watch: { watch: {
active(val) { active(val) {
this.correctActive(val); if (val !== this.curActive) {
this.correctActive(val);
}
}, },
tabs(tabs) { tabs(tabs) {
@ -166,9 +172,9 @@ export default create({
if (direction === 'horizontal' && this.offsetX >= minSwipeDistance) { if (direction === 'horizontal' && this.offsetX >= minSwipeDistance) {
/* istanbul ignore else */ /* istanbul ignore else */
if (deltaX > 0 && curActive !== 0) { if (deltaX > 0 && curActive !== 0) {
this.curActive = curActive - 1; this.setCurActive(curActive - 1);
} else if (deltaX < 0 && curActive !== this.tabs.length - 1) { } else if (deltaX < 0 && curActive !== this.tabs.length - 1) {
this.curActive = curActive + 1; this.setCurActive(curActive + 1);
} }
} }
}, },
@ -208,7 +214,12 @@ export default create({
active = +active; active = +active;
const exist = this.tabs.some(tab => tab.index === active); const exist = this.tabs.some(tab => tab.index === active);
const defaultActive = (this.tabs[0] || {}).index || 0; const defaultActive = (this.tabs[0] || {}).index || 0;
this.curActive = exist ? active : defaultActive; this.setCurActive(exist ? active : defaultActive);
},
setCurActive(active) {
this.curActive = active;
this.$emit('input', active);
}, },
// emit event when clicked // emit event when clicked
@ -218,7 +229,7 @@ export default create({
this.$emit('disabled', index, title); this.$emit('disabled', index, title);
} else { } else {
this.$emit('click', index, title); this.$emit('click', index, title);
this.curActive = index; this.setCurActive(index);
} }
}, },