mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat(Cascader): select options
This commit is contained in:
parent
0352f5d9a6
commit
347758a935
src
@ -1,6 +1,7 @@
|
||||
import { createNamespace } from '../utils';
|
||||
import Tab from '../tab';
|
||||
import Tabs from '../tabs';
|
||||
import Icon from '../icon';
|
||||
|
||||
const [createComponent, bem] = createNamespace('cascader');
|
||||
|
||||
@ -47,12 +48,40 @@ export default createComponent({
|
||||
{
|
||||
title: this.placeholder || this.t('placeholder'),
|
||||
options: this.options,
|
||||
selected: null,
|
||||
},
|
||||
];
|
||||
}
|
||||
},
|
||||
|
||||
genHeader() {
|
||||
onSelect(option, tabIndex) {
|
||||
this.tabs[tabIndex].title = option.text;
|
||||
this.tabs[tabIndex].selected = option.value;
|
||||
|
||||
if (this.tabs.length > tabIndex + 1) {
|
||||
this.tabs = this.tabs.slice(0, tabIndex + 1);
|
||||
}
|
||||
|
||||
if (option.children) {
|
||||
const nextTab = {
|
||||
title: this.placeholder || this.t('placeholder'),
|
||||
options: option.children,
|
||||
selected: null,
|
||||
};
|
||||
|
||||
if (this.tabs[tabIndex + 1]) {
|
||||
this.$set(this.tabs, tabIndex + 1, nextTab);
|
||||
} else {
|
||||
this.tabs.push(nextTab);
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.activeTab++;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
renderHeader() {
|
||||
return (
|
||||
<div class={bem('header')}>
|
||||
<h2 class={bem('title')}>{this.slots('title') || this.title}</h2>
|
||||
@ -60,23 +89,41 @@ export default createComponent({
|
||||
);
|
||||
},
|
||||
|
||||
genTabs() {
|
||||
renderOptions(options, selected, tabIndex) {
|
||||
return (
|
||||
<Tabs class={bem('tabs')}>
|
||||
{this.tabs.map((item) => (
|
||||
<Tab title={item.title}>{this.genOptions(item.options)}</Tab>
|
||||
))}
|
||||
</Tabs>
|
||||
<ul class={bem('options')}>
|
||||
{options.map((option) => {
|
||||
const isSelected = option.value === selected;
|
||||
return (
|
||||
<li
|
||||
class={bem('option', { selected: isSelected })}
|
||||
onClick={() => {
|
||||
this.onSelect(option, tabIndex);
|
||||
}}
|
||||
>
|
||||
<span>{option.text}</span>
|
||||
{isSelected ? (
|
||||
<Icon name="success" class={bem('selected-icon')} />
|
||||
) : null}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
},
|
||||
|
||||
genOptions(options) {
|
||||
renderTabs() {
|
||||
return (
|
||||
<ul class={bem('options')}>
|
||||
{options.map((option) => (
|
||||
<li class={bem('option')}>{option.text}</li>
|
||||
<Tabs vModel={this.activeTab} animated swipeable class={bem('tabs')}>
|
||||
{this.tabs.map((item, tabIndex) => (
|
||||
<Tab
|
||||
title={item.title}
|
||||
titleClass={bem('tab-title', { unselected: !item.selected })}
|
||||
>
|
||||
{this.renderOptions(item.options, item.selected, tabIndex)}
|
||||
</Tab>
|
||||
))}
|
||||
</ul>
|
||||
</Tabs>
|
||||
);
|
||||
},
|
||||
},
|
||||
@ -84,8 +131,8 @@ export default createComponent({
|
||||
render() {
|
||||
return (
|
||||
<div class={bem()}>
|
||||
{this.genHeader()}
|
||||
{this.genTabs()}
|
||||
{this.renderHeader()}
|
||||
{this.renderTabs()}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@ -19,10 +19,6 @@
|
||||
.van-tab {
|
||||
flex: none;
|
||||
padding: 0 10px;
|
||||
|
||||
&--active {
|
||||
color: #969799;
|
||||
}
|
||||
}
|
||||
|
||||
&.van-tabs--line .van-tabs__wrap {
|
||||
@ -31,19 +27,42 @@
|
||||
}
|
||||
}
|
||||
|
||||
&__tab-title {
|
||||
color: @gray-8;
|
||||
font-weight: @font-weight-bold;
|
||||
|
||||
&--unselected {
|
||||
color: @gray-6;
|
||||
}
|
||||
}
|
||||
|
||||
&__option {
|
||||
padding: 10px 16px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px @padding-md;
|
||||
font-size: @font-size-md;
|
||||
line-height: @line-height-md;
|
||||
|
||||
&:active {
|
||||
background-color: @active-color;
|
||||
}
|
||||
|
||||
&--selected {
|
||||
color: @red;
|
||||
}
|
||||
}
|
||||
|
||||
&__selected-icon {
|
||||
color: @red;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
&__options {
|
||||
box-sizing: border-box;
|
||||
height: 384px;
|
||||
padding-top: 6px;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
}
|
||||
|
@ -252,6 +252,7 @@ export default {
|
||||
| to | Target route of the link, same as to of vue-router | _string \| object_ | - |
|
||||
| replace | If true, the navigation will not leave a history record | _boolean_ | `false` |
|
||||
| title-style | Custom title style | _any_ | - |
|
||||
| title-class | Custom title class name | _any_ | - |
|
||||
|
||||
### Tabs Events
|
||||
|
||||
|
@ -260,6 +260,7 @@ export default {
|
||||
| to | 点击后跳转的目标路由对象,同 vue-router 的 [to 属性](https://router.vuejs.org/zh/api/#to) | _string \| object_ | - |
|
||||
| replace | 是否在跳转时替换当前页面历史 | _boolean_ | `false` |
|
||||
| title-style | 自定义标题样式 | _any_ | - |
|
||||
| title-class | 自定义标题类名 | _any_ | - |
|
||||
|
||||
### Tabs Events
|
||||
|
||||
|
@ -16,6 +16,7 @@ export default createComponent({
|
||||
badge: [Number, String],
|
||||
title: String,
|
||||
titleStyle: null,
|
||||
titleClass: null,
|
||||
disabled: Boolean,
|
||||
},
|
||||
|
||||
|
@ -372,6 +372,7 @@ export default createComponent({
|
||||
title={item.title}
|
||||
color={this.color}
|
||||
style={item.titleStyle}
|
||||
class={item.titleClass}
|
||||
isActive={index === this.currentIndex}
|
||||
disabled={item.disabled}
|
||||
scrollable={scrollable}
|
||||
|
Loading…
x
Reference in New Issue
Block a user