mirror of
https://github.com/youzan/vant.git
synced 2025-10-21 19:24:16 +00:00
[improvement] rename packages dir to src (#3659)
This commit is contained in:
135
src/tree-select/demo/index.vue
Normal file
135
src/tree-select/demo/index.vue
Normal file
@@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<demo-section>
|
||||
<demo-block :title="$t('basicUsage')">
|
||||
<van-tree-select
|
||||
:items="items"
|
||||
:main-active-index="mainActiveIndex"
|
||||
:active-id="activeId"
|
||||
@navclick="onNavClick"
|
||||
@itemclick="onItemClick"
|
||||
/>
|
||||
</demo-block>
|
||||
</demo-section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
i18n: {
|
||||
'zh-CN': {
|
||||
group1: '所有城市',
|
||||
group2: '浙江',
|
||||
group3: '江苏',
|
||||
group4: '福建',
|
||||
city1: [{
|
||||
text: '杭州',
|
||||
id: 1
|
||||
}, {
|
||||
text: '温州',
|
||||
id: 2
|
||||
}, {
|
||||
text: '宁波',
|
||||
id: 3,
|
||||
disabled: true
|
||||
}, {
|
||||
text: '义乌',
|
||||
id: 4
|
||||
}],
|
||||
city2: [{
|
||||
text: '南京',
|
||||
id: 5
|
||||
}, {
|
||||
text: '无锡',
|
||||
id: 6
|
||||
}, {
|
||||
text: '徐州',
|
||||
id: 7
|
||||
}, {
|
||||
text: '苏州',
|
||||
id: 8
|
||||
}],
|
||||
city3: [{
|
||||
text: '泉州',
|
||||
id: 9
|
||||
}, {
|
||||
text: '厦门',
|
||||
id: 10
|
||||
}]
|
||||
},
|
||||
'en-US': {
|
||||
group1: 'All',
|
||||
group2: 'Group1',
|
||||
group3: 'Group2',
|
||||
group4: 'Group3',
|
||||
city1: [{
|
||||
text: 'Delaware',
|
||||
id: 1
|
||||
}, {
|
||||
text: 'Florida',
|
||||
id: 2
|
||||
}, {
|
||||
text: 'Georqia',
|
||||
id: 3,
|
||||
disabled: true
|
||||
}, {
|
||||
text: 'Indiana',
|
||||
id: 4
|
||||
}],
|
||||
city2: [{
|
||||
text: 'Alabama',
|
||||
id: 5
|
||||
}, {
|
||||
text: 'Kansas',
|
||||
id: 6
|
||||
}, {
|
||||
text: 'Louisiana',
|
||||
id: 7
|
||||
}, {
|
||||
text: 'Texas',
|
||||
id: 8
|
||||
}],
|
||||
city3: [{
|
||||
text: 'Alabama',
|
||||
id: 9
|
||||
}, {
|
||||
text: 'Kansas',
|
||||
id: 10
|
||||
}],
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
mainActiveIndex: 0,
|
||||
activeId: 1
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
items() {
|
||||
return [{
|
||||
text: this.$t('group1'),
|
||||
children: [...this.$t('city1'), ...this.$t('city2')]
|
||||
}, {
|
||||
text: this.$t('group2'),
|
||||
children: this.$t('city1')
|
||||
}, {
|
||||
text: this.$t('group3'),
|
||||
children: this.$t('city2')
|
||||
}, {
|
||||
text: this.$t('group4'),
|
||||
disabled: true,
|
||||
children: this.$t('city3')
|
||||
}];
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onNavClick(index) {
|
||||
this.mainActiveIndex = index;
|
||||
},
|
||||
onItemClick(data) {
|
||||
this.activeId = data.id;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
93
src/tree-select/en-US.md
Normal file
93
src/tree-select/en-US.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# TreeSelect
|
||||
|
||||
### Install
|
||||
|
||||
``` javascript
|
||||
import { TreeSelect } from 'vant';
|
||||
|
||||
Vue.use(TreeSelect);
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```html
|
||||
<van-tree-select
|
||||
:items="items"
|
||||
:main-active-index="mainActiveIndex"
|
||||
:active-id="activeId"
|
||||
@navclick="onNavClick"
|
||||
@itemclick="onItemClick"
|
||||
/>
|
||||
```
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
items,
|
||||
// the index of parent item
|
||||
mainActiveIndex: 0,
|
||||
// the id of selected item
|
||||
activeId: 1001
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onNavClick(index) {
|
||||
this.mainActiveIndex = index;
|
||||
},
|
||||
onItemClick(data) {
|
||||
this.activeId = data.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
|------|------|------|------|
|
||||
| items | Required datasets for the component, see Data Structure for detail. | `Array` | `[]` |
|
||||
| height | Height (px) | `Number` | `300` |
|
||||
| main-Active-index | The index of selected parent node | `Number` | `0` |
|
||||
| active-id | Id of selected item | `String | Number` | `0` |
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Description | Arguments |
|
||||
|------|------|------|
|
||||
| navclick | triggered when parent node is selected | index: index of selected parent |
|
||||
| itemclick | triggered when item is selected | data: selected item |
|
||||
|
||||
### Data Structure
|
||||
|
||||
`items` should be an array contains specified tree objects.
|
||||
|
||||
In every tree object, `text` property defines `id` stands for the unique key while the `children` contains sub-tree objects.
|
||||
|
||||
```javascript
|
||||
[
|
||||
{
|
||||
// name of the parent node
|
||||
text: 'All Cities',
|
||||
// leaves of this parent node
|
||||
children: [
|
||||
{
|
||||
// name of the leaf node
|
||||
text: 'Washington',
|
||||
// id of the leaf node, component highlights leaf node by comparing the activeId with this.
|
||||
id: 1,
|
||||
// disable options
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
text: 'Baltimore',
|
||||
id: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
61
src/tree-select/index.less
Normal file
61
src/tree-select/index.less
Normal file
@@ -0,0 +1,61 @@
|
||||
@import '../style/var';
|
||||
|
||||
.van-tree-select {
|
||||
position: relative;
|
||||
display: flex;
|
||||
font-size: @tree-select-font-size;
|
||||
user-select: none;
|
||||
|
||||
&__nav {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
background-color: @tree-select-nav-background-color;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
&-item {
|
||||
position: relative;
|
||||
padding: @tree-select-nav-item-padding;
|
||||
line-height: @tree-select-item-height;
|
||||
border-left: 3px solid transparent;
|
||||
|
||||
&--active {
|
||||
font-weight: bold;
|
||||
background-color: @tree-select-nav-item-active-background-color;
|
||||
border-color: @tree-select-nav-item-active-border-color;
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
color: @tree-select-nav-item-disabled-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__content {
|
||||
flex: 2;
|
||||
overflow-y: auto;
|
||||
background-color: @tree-select-content-background-color;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
&__item {
|
||||
position: relative;
|
||||
padding-left: 15px;
|
||||
font-weight: bold;
|
||||
line-height: @tree-select-item-height;
|
||||
|
||||
&--active {
|
||||
color: @tree-select-item-active-color;
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
color: @tree-select-item-disabled-color;
|
||||
}
|
||||
}
|
||||
|
||||
&__selected {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 15px;
|
||||
margin-top: -8px;
|
||||
}
|
||||
}
|
105
src/tree-select/index.tsx
Normal file
105
src/tree-select/index.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import { createNamespace } from '../utils';
|
||||
import { emit, inherit } from '../utils/functional';
|
||||
import Icon from '../icon';
|
||||
|
||||
// Types
|
||||
import { CreateElement, RenderContext } from 'vue/types';
|
||||
import { DefaultSlots } from '../utils/types';
|
||||
|
||||
export type TreeSelectItem = {
|
||||
text: string;
|
||||
disabled?: boolean;
|
||||
children: TreeSelectChildren[];
|
||||
};
|
||||
|
||||
export type TreeSelectChildren = {
|
||||
id: number;
|
||||
text: string;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export type TreeSelectProps = {
|
||||
height: number;
|
||||
items: TreeSelectItem[];
|
||||
activeId: number | string;
|
||||
mainActiveIndex: number;
|
||||
};
|
||||
|
||||
const [createComponent, bem] = createNamespace('tree-select');
|
||||
|
||||
function TreeSelect(
|
||||
h: CreateElement,
|
||||
props: TreeSelectProps,
|
||||
slots: DefaultSlots,
|
||||
ctx: RenderContext<TreeSelectProps>
|
||||
) {
|
||||
const { height, items, mainActiveIndex, activeId } = props;
|
||||
|
||||
const selectedItem = items[mainActiveIndex] || {};
|
||||
const subItems = selectedItem.children || [];
|
||||
|
||||
return (
|
||||
<div class={bem()} style={{ height: `${height}px` }} {...inherit(ctx)}>
|
||||
<div class={bem('nav')}>
|
||||
{items.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
class={[
|
||||
'van-ellipsis',
|
||||
bem('nav-item', {
|
||||
active: mainActiveIndex === index,
|
||||
disabled: item.disabled
|
||||
})
|
||||
]}
|
||||
onClick={() => {
|
||||
if (!item.disabled) {
|
||||
emit(ctx, 'navclick', index);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{item.text}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div class={bem('content')}>
|
||||
{subItems.map(item => (
|
||||
<div
|
||||
key={item.id}
|
||||
class={[
|
||||
'van-ellipsis',
|
||||
bem('item', {
|
||||
active: activeId === item.id,
|
||||
disabled: item.disabled
|
||||
})
|
||||
]}
|
||||
onClick={() => {
|
||||
if (!item.disabled) {
|
||||
emit(ctx, 'itemclick', item);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{item.text}
|
||||
{activeId === item.id && (
|
||||
<Icon name="checked" size="16px" class={bem('selected')} />
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
TreeSelect.props = {
|
||||
items: Array,
|
||||
mainActiveIndex: Number,
|
||||
activeId: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 300
|
||||
}
|
||||
};
|
||||
|
||||
export default createComponent<TreeSelectProps>(TreeSelect);
|
27
src/tree-select/test/__snapshots__/demo.spec.js.snap
Normal file
27
src/tree-select/test/__snapshots__/demo.spec.js.snap
Normal file
@@ -0,0 +1,27 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders demo correctly 1`] = `
|
||||
<div>
|
||||
<div>
|
||||
<div class="van-tree-select" style="height: 300px;">
|
||||
<div class="van-tree-select__nav">
|
||||
<div class="van-ellipsis van-tree-select__nav-item van-tree-select__nav-item--active">所有城市</div>
|
||||
<div class="van-ellipsis van-tree-select__nav-item">浙江</div>
|
||||
<div class="van-ellipsis van-tree-select__nav-item">江苏</div>
|
||||
<div class="van-ellipsis van-tree-select__nav-item van-tree-select__nav-item--disabled">福建</div>
|
||||
</div>
|
||||
<div class="van-tree-select__content">
|
||||
<div class="van-ellipsis van-tree-select__item van-tree-select__item--active">杭州<i class="van-icon van-icon-checked van-tree-select__selected" style="font-size: 16px;">
|
||||
<!----></i></div>
|
||||
<div class="van-ellipsis van-tree-select__item">温州</div>
|
||||
<div class="van-ellipsis van-tree-select__item van-tree-select__item--disabled">宁波</div>
|
||||
<div class="van-ellipsis van-tree-select__item">义乌</div>
|
||||
<div class="van-ellipsis van-tree-select__item">南京</div>
|
||||
<div class="van-ellipsis van-tree-select__item">无锡</div>
|
||||
<div class="van-ellipsis van-tree-select__item">徐州</div>
|
||||
<div class="van-ellipsis van-tree-select__item">苏州</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
8
src/tree-select/test/__snapshots__/index.spec.js.snap
Normal file
8
src/tree-select/test/__snapshots__/index.spec.js.snap
Normal file
@@ -0,0 +1,8 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`empty list 1`] = `
|
||||
<div class="van-tree-select" style="height: 300px;">
|
||||
<div class="van-tree-select__nav"></div>
|
||||
<div class="van-tree-select__content"></div>
|
||||
</div>
|
||||
`;
|
4
src/tree-select/test/demo.spec.js
Normal file
4
src/tree-select/test/demo.spec.js
Normal file
@@ -0,0 +1,4 @@
|
||||
import Demo from '../demo';
|
||||
import demoTest from '../../../test/demo-test';
|
||||
|
||||
demoTest(Demo);
|
37
src/tree-select/test/index.spec.js
Normal file
37
src/tree-select/test/index.spec.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import TreeSelect from '..';
|
||||
import { mount } from '../../../test/utils';
|
||||
|
||||
test('empty list', () => {
|
||||
expect(mount(TreeSelect)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('select item', () => {
|
||||
const onItemClick = jest.fn();
|
||||
const item = {
|
||||
text: 'city1',
|
||||
id: 1
|
||||
};
|
||||
|
||||
const wrapper = mount(TreeSelect, {
|
||||
propsData: {
|
||||
items: [{
|
||||
text: 'group1',
|
||||
children: [
|
||||
item,
|
||||
{ ...item, disabled: true }
|
||||
]
|
||||
}]
|
||||
},
|
||||
context: {
|
||||
on: {
|
||||
itemclick: onItemClick
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const items = wrapper.findAll('.van-tree-select__item');
|
||||
items.at(0).trigger('click');
|
||||
expect(onItemClick).toHaveBeenCalledWith(item);
|
||||
items.at(1).trigger('click');
|
||||
expect(onItemClick).toHaveBeenCalledTimes(1);
|
||||
});
|
93
src/tree-select/zh-CN.md
Normal file
93
src/tree-select/zh-CN.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# TreeSelect 分类选择
|
||||
|
||||
### 引入
|
||||
|
||||
``` javascript
|
||||
import { TreeSelect } from 'vant';
|
||||
|
||||
Vue.use(TreeSelect);
|
||||
```
|
||||
|
||||
## 代码演示
|
||||
|
||||
### 基础用法
|
||||
|
||||
```html
|
||||
<van-tree-select
|
||||
:items="items"
|
||||
:main-active-index="mainActiveIndex"
|
||||
:active-id="activeId"
|
||||
@navclick="onNavClick"
|
||||
@itemclick="onItemClick"
|
||||
/>
|
||||
```
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
items,
|
||||
// 左侧高亮元素的index
|
||||
mainActiveIndex: 0,
|
||||
// 被选中元素的id
|
||||
activeId: 1
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onNavClick(index) {
|
||||
this.mainActiveIndex = index;
|
||||
},
|
||||
onItemClick(data) {
|
||||
this.activeId = data.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
|------|------|------|------|------|
|
||||
| items | 分类显示所需的数据,结构参见下方 | `Array` | `[]` | - |
|
||||
| height | 高度,单位为 px | `Number` | `300` | 1.3.6 |
|
||||
| main-active-index | 左侧导航高亮的索引 | `Number` | `0` | - |
|
||||
| active-id | 右侧选择项,高亮的数据id | `String | Number` | `0` | - |
|
||||
|
||||
### Events
|
||||
|
||||
| 事件名 | 说明 | 回调参数 |
|
||||
|------|------|------|
|
||||
| navclick | 左侧导航点击时,触发的事件 | index:被点击的导航的索引 |
|
||||
| itemclick | 右侧选择项被点击时,会触发的事件 | data: 该点击项的数据 |
|
||||
|
||||
### items 分类显示所需数据的数据结构
|
||||
|
||||
`items` 整体为一个数组,数组内包含一系列描述分类的对象。
|
||||
|
||||
每个分类里,text 表示当前分类的名称。children 表示分类里的可选项,为数组结构,id 被用来唯一标识每个选项
|
||||
|
||||
```javascript
|
||||
[
|
||||
{
|
||||
// 导航名称
|
||||
text: '所有城市',
|
||||
// 该导航下所有的可选项
|
||||
children: [
|
||||
{
|
||||
// 名称
|
||||
text: '温州',
|
||||
// id,作为匹配选中状态的标识
|
||||
id: 1,
|
||||
// 禁用选项
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
text: '杭州',
|
||||
id: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
Reference in New Issue
Block a user