mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat: migrate TreeSelect component
This commit is contained in:
parent
d04c8c1e24
commit
7a197fc90f
@ -1,6 +1,24 @@
|
|||||||
# 不兼容更新
|
# 不兼容更新
|
||||||
|
|
||||||
## 重命名徽标属性
|
## v-model API 变更
|
||||||
|
|
||||||
|
以下改动是为了适配 Vue 3 的 v-model API 用法变更:
|
||||||
|
|
||||||
|
- Circle: `v-model` 重命名为 `v-model:currentRate`
|
||||||
|
- Popup: `v-model` 重命名为 `v-model:show`
|
||||||
|
- Switch: v-model 对应的属性 `value` 重命名为 `modelValue`,事件由 `input` 重命名为 `update:modelValue`
|
||||||
|
- Sidebar: v-model 对应的属性 `activeKey` 重命名为 `modelValue`,事件由 `input` 重命名为 `update:modelValue`
|
||||||
|
- TreeSelect: `active-id.sync` 重命名为 `v-model:active-id`
|
||||||
|
- TreeSelect: `main-active-index.sync` 重命名为 `v-model:main-active-index`
|
||||||
|
|
||||||
|
## API 命名调整
|
||||||
|
|
||||||
|
以下改动是为了规范 API 命名:
|
||||||
|
|
||||||
|
- TreeSelect: `navclick` 事件重命名为 `click-nav`
|
||||||
|
- TreeSelect: `itemclick` 事件重命名为 `click-item`
|
||||||
|
|
||||||
|
### 重命名徽标属性
|
||||||
|
|
||||||
在之前的版本中,我们通过 info 属性来展示图标右上角的徽标信息,为了表达更符合社区的命名习惯,我们将这个属性重命名为 badge,影响以下组件:
|
在之前的版本中,我们通过 info 属性来展示图标右上角的徽标信息,为了表达更符合社区的命名习惯,我们将这个属性重命名为 badge,影响以下组件:
|
||||||
|
|
||||||
@ -14,13 +32,6 @@
|
|||||||
|
|
||||||
同时内部使用的 Info 组件也会重命名为 Badge。
|
同时内部使用的 Info 组件也会重命名为 Badge。
|
||||||
|
|
||||||
## v-model API 变更
|
|
||||||
|
|
||||||
- Circle: `v-model` 调整为 `v-model:currentRate`
|
|
||||||
- Popup: `v-model` 调整为 `v-model:show`
|
|
||||||
- Switch: v-model 对应的属性 `value` 调整为 `modelValue`,事件由 `input` 调整为 `update:modelValue`
|
|
||||||
- Sidebar: v-model 对应的属性 `activeKey` 调整为 `modelValue`,事件由 `input` 调整为 `update:modelValue`
|
|
||||||
|
|
||||||
## 废弃个别组件
|
## 废弃个别组件
|
||||||
|
|
||||||
- SwitchCell: 移除此组件,可以直接使用 Cell 和 Switch 组件代替
|
- SwitchCell: 移除此组件,可以直接使用 Cell 和 Switch 组件代替
|
||||||
|
170
src-next/tree-select/README.md
Normal file
170
src-next/tree-select/README.md
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
# TreeSelect
|
||||||
|
|
||||||
|
### Install
|
||||||
|
|
||||||
|
```js
|
||||||
|
import Vue from 'vue';
|
||||||
|
import { TreeSelect } from 'vant';
|
||||||
|
|
||||||
|
Vue.use(TreeSelect);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Radio Mode
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-tree-select
|
||||||
|
v-model:active-id="activeId"
|
||||||
|
v-model:main-active-index="activeIndex"
|
||||||
|
:items="items"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
items,
|
||||||
|
activeId: 1,
|
||||||
|
activeIndex: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple Mode
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-tree-select
|
||||||
|
v-model:active-id="activeIds"
|
||||||
|
v-model:main-active-index="activeIndex"
|
||||||
|
:items="items"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
items,
|
||||||
|
activeIds: [1, 2],
|
||||||
|
activeIndex: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Content
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-tree-select v-model:main-active-index="active" height="55vw" :items="items">
|
||||||
|
<template #content>
|
||||||
|
<van-image
|
||||||
|
v-if="active === 0"
|
||||||
|
src="https://img.yzcdn.cn/vant/apple-1.jpg"
|
||||||
|
/>
|
||||||
|
<van-image
|
||||||
|
v-if="active === 1"
|
||||||
|
src="https://img.yzcdn.cn/vant/apple-2.jpg"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</van-tree-select>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
active: 0,
|
||||||
|
items: [{ text: 'Group 1' }, { text: 'Group 2' }],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Show Badge
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-tree-select
|
||||||
|
v-model:main-active-index="activeIndex"
|
||||||
|
height="55vw"
|
||||||
|
:items="items"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeIndex: 0,
|
||||||
|
items: [
|
||||||
|
{ text: 'Group 1', children: [], dot: true },
|
||||||
|
{ text: 'Group 2', children: [], badge: 5 },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
| Attribute | Description | Type | Default |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| items | Required datasets for the component | _Item[]_ | `[]` |
|
||||||
|
| height | Height | _number \| string_ | `300` |
|
||||||
|
| main-active-index | The index of selected parent node | _number \| string_ | `0` |
|
||||||
|
| active-id | Id of selected item | _number \| string \|<br>(number \| string)[]_ | `0` |
|
||||||
|
| max `v2.2.0` | Maximum number of selected items | _number \| string_ | `Infinity` |
|
||||||
|
| selected-icon `v2.9.0` | Selected icon | _string_ | `success` |
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
| Event | Description | Arguments |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| click-nav | triggered when parent node is selected | index: index of selected parent |
|
||||||
|
| click-item | triggered when item is selected | data: selected item |
|
||||||
|
|
||||||
|
### Slots
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
| ------- | -------------------- |
|
||||||
|
| content | Custom right content |
|
||||||
|
|
||||||
|
### Data Structure of Item
|
||||||
|
|
||||||
|
`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.
|
||||||
|
|
||||||
|
```js
|
||||||
|
[
|
||||||
|
{
|
||||||
|
// name of the parent node
|
||||||
|
text: 'Group 1',
|
||||||
|
// badge
|
||||||
|
badge: 3,
|
||||||
|
// Whether to show red dot
|
||||||
|
dot: true,
|
||||||
|
// ClassName of parent node
|
||||||
|
className: 'my-class',
|
||||||
|
// 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,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
```
|
180
src-next/tree-select/README.zh-CN.md
Normal file
180
src-next/tree-select/README.zh-CN.md
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
# TreeSelect 分类选择
|
||||||
|
|
||||||
|
### 引入
|
||||||
|
|
||||||
|
```js
|
||||||
|
import Vue from 'vue';
|
||||||
|
import { TreeSelect } from 'vant';
|
||||||
|
|
||||||
|
Vue.use(TreeSelect);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 代码演示
|
||||||
|
|
||||||
|
### 单选模式
|
||||||
|
|
||||||
|
`item`为分类显示所需的数据,数据格式见下方示例。`main-active-index`表示左侧高亮选项的索引,`active-id`表示右侧高亮选项的 id
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-tree-select
|
||||||
|
v-model:active-id="activeId"
|
||||||
|
v-model:main-active-index="activeIndex"
|
||||||
|
:items="items"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
items,
|
||||||
|
activeId: 1,
|
||||||
|
activeIndex: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 多选模式
|
||||||
|
|
||||||
|
`active-id`为数组格式时,可以选中多个右侧选项
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-tree-select
|
||||||
|
v-model:active-id="activeIds"
|
||||||
|
v-model:main-active-index="activeIndex"
|
||||||
|
:items="items"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
items,
|
||||||
|
activeIds: [1, 2],
|
||||||
|
activeIndex: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自定义内容
|
||||||
|
|
||||||
|
通过`content`插槽可以自定义右侧区域的内容
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-tree-select
|
||||||
|
v-model:main-active-index="active"
|
||||||
|
height="55vw"
|
||||||
|
:items="items"
|
||||||
|
>
|
||||||
|
<template #content>
|
||||||
|
<van-image
|
||||||
|
v-if="active === 0"
|
||||||
|
src="https://img.yzcdn.cn/vant/apple-1.jpg"
|
||||||
|
/>
|
||||||
|
<van-image
|
||||||
|
v-if="active === 1"
|
||||||
|
src="https://img.yzcdn.cn/vant/apple-2.jpg"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</van-tree-select>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
active: 0,
|
||||||
|
items: [{ text: '分组 1' }, { text: '分组 2' }],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 徽标提示
|
||||||
|
|
||||||
|
设置`dot`属性后,会在图标右上角展示一个小红点。设置`badge`属性后,会在图标右上角展示相应的徽标
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-tree-select
|
||||||
|
v-model:main-active-index="activeIndex"
|
||||||
|
height="55vw"
|
||||||
|
:items="items"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeIndex: 0,
|
||||||
|
items: [
|
||||||
|
{ text: '浙江', children: [], dot: true },
|
||||||
|
{ text: '江苏', children: [], badge: 5 },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| items | 分类显示所需的数据 | _Item[]_ | `[]` |
|
||||||
|
| height | 高度,默认单位为`px` | _number \| string_ | `300` |
|
||||||
|
| main-active-index | 左侧选中项的索引 | _number \| string_ | `0` |
|
||||||
|
| active-id | 右侧选中项的 id,支持传入数组 | _number \| string \|<br>(number \| string)[]_ | `0` |
|
||||||
|
| max `v2.2.0` | 右侧项最大选中个数 | _number \| string_ | `Infinity` |
|
||||||
|
| selected-icon `v2.9.0` | 自定义右侧栏选中状态的图标 | _string_ | `success` |
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
| 事件名 | 说明 | 回调参数 |
|
||||||
|
| ---------- | -------------------- | ------------------------- |
|
||||||
|
| click-nav | 点击左侧导航时触发 | index:被点击的导航的索引 |
|
||||||
|
| click-item | 点击右侧选择项时触发 | data: 该点击项的数据 |
|
||||||
|
|
||||||
|
### Slots
|
||||||
|
|
||||||
|
| 名称 | 说明 |
|
||||||
|
| ------- | ------------------ |
|
||||||
|
| content | 自定义右侧区域内容 |
|
||||||
|
|
||||||
|
### Item 数据结构
|
||||||
|
|
||||||
|
`items` 整体为一个数组,数组内包含一系列描述分类的对象,每个分类里,`text`表示当前分类的名称,`children`表示分类里的可选项。
|
||||||
|
|
||||||
|
```js
|
||||||
|
[
|
||||||
|
{
|
||||||
|
// 导航名称
|
||||||
|
text: '所有城市',
|
||||||
|
// 导航名称右上角徽标,2.5.6 版本开始支持
|
||||||
|
badge: 3,
|
||||||
|
// 是否在导航名称右上角显示小红点
|
||||||
|
dot: true,
|
||||||
|
// 导航节点额外类名
|
||||||
|
className: 'my-class',
|
||||||
|
// 该导航下所有的可选项
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
// 名称
|
||||||
|
text: '温州',
|
||||||
|
// id,作为匹配选中状态的标识符
|
||||||
|
id: 1,
|
||||||
|
// 禁用选项
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '杭州',
|
||||||
|
id: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
```
|
65
src-next/tree-select/demo/data-en.ts
Normal file
65
src-next/tree-select/demo/data-en.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
const group1 = [
|
||||||
|
{
|
||||||
|
text: 'Delaware',
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Florida',
|
||||||
|
id: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Georqia',
|
||||||
|
id: 3,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Indiana',
|
||||||
|
id: 4,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const group2 = [
|
||||||
|
{
|
||||||
|
text: 'Alabama',
|
||||||
|
id: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Kansas',
|
||||||
|
id: 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Louisiana',
|
||||||
|
id: 7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Texas',
|
||||||
|
id: 8,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const group3 = [
|
||||||
|
{
|
||||||
|
text: 'Alabama',
|
||||||
|
id: 9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Kansas',
|
||||||
|
id: 10,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const enUSData = [
|
||||||
|
{
|
||||||
|
text: 'Group 1',
|
||||||
|
children: group1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Group 2',
|
||||||
|
children: group2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Group 3',
|
||||||
|
disabled: true,
|
||||||
|
children: group3,
|
||||||
|
},
|
||||||
|
];
|
65
src-next/tree-select/demo/data-zh.ts
Normal file
65
src-next/tree-select/demo/data-zh.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
const zhejiang = [
|
||||||
|
{
|
||||||
|
text: '杭州',
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '温州',
|
||||||
|
id: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '宁波',
|
||||||
|
id: 3,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '义乌',
|
||||||
|
id: 4,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const jiangsu = [
|
||||||
|
{
|
||||||
|
text: '南京',
|
||||||
|
id: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '无锡',
|
||||||
|
id: 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '徐州',
|
||||||
|
id: 7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '苏州',
|
||||||
|
id: 8,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const fujian = [
|
||||||
|
{
|
||||||
|
text: '泉州',
|
||||||
|
id: 9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '厦门',
|
||||||
|
id: 10,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const zhCNData = [
|
||||||
|
{
|
||||||
|
text: '浙江',
|
||||||
|
children: zhejiang,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '江苏',
|
||||||
|
children: jiangsu,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '福建',
|
||||||
|
disabled: true,
|
||||||
|
children: fujian,
|
||||||
|
},
|
||||||
|
];
|
107
src-next/tree-select/demo/index.vue
Normal file
107
src-next/tree-select/demo/index.vue
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<template>
|
||||||
|
<demo-section>
|
||||||
|
<demo-block :title="t('radioMode')">
|
||||||
|
<van-tree-select
|
||||||
|
v-model:active-id="activeId"
|
||||||
|
v-model:main-active-index="activeIndex"
|
||||||
|
:items="items"
|
||||||
|
/>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('multipleMode')">
|
||||||
|
<van-tree-select
|
||||||
|
v-model:active-id="activeIds"
|
||||||
|
v-model:main-active-index="activeIndex2"
|
||||||
|
:items="items"
|
||||||
|
/>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('customContent')">
|
||||||
|
<van-tree-select
|
||||||
|
v-model:main-active-index="activeIndex3"
|
||||||
|
height="55vw"
|
||||||
|
:items="simpleItems"
|
||||||
|
>
|
||||||
|
<template slot="content">
|
||||||
|
<van-image
|
||||||
|
v-if="activeIndex3 === 0"
|
||||||
|
:show-loading="false"
|
||||||
|
src="https://img.yzcdn.cn/vant/apple-1.jpg"
|
||||||
|
/>
|
||||||
|
<van-image
|
||||||
|
v-if="activeIndex3 === 1"
|
||||||
|
:show-loading="false"
|
||||||
|
src="https://img.yzcdn.cn/vant/apple-2.jpg"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</van-tree-select>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('showBadge')">
|
||||||
|
<van-tree-select
|
||||||
|
v-model:active-id="activeId2"
|
||||||
|
v-model:main-active-index="activeIndex4"
|
||||||
|
height="55vw"
|
||||||
|
:items="badgeItems"
|
||||||
|
/>
|
||||||
|
</demo-block>
|
||||||
|
</demo-section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { zhCNData } from './data-zh';
|
||||||
|
import { enUSData } from './data-en';
|
||||||
|
import { deepClone } from '../../utils/deep-clone';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
i18n: {
|
||||||
|
'zh-CN': {
|
||||||
|
showBadge: '徽标提示',
|
||||||
|
radioMode: '单选模式',
|
||||||
|
multipleMode: '多选模式',
|
||||||
|
customContent: '自定义内容',
|
||||||
|
data: zhCNData,
|
||||||
|
dataSimple: [{ text: '分组 1' }, { text: '分组 2' }],
|
||||||
|
},
|
||||||
|
'en-US': {
|
||||||
|
showBadge: 'Show Badge',
|
||||||
|
radioMode: 'Radio Mode',
|
||||||
|
multipleMode: 'Multiple Mode',
|
||||||
|
customContent: 'Custom Content',
|
||||||
|
data: enUSData,
|
||||||
|
dataSimple: [{ text: 'Group 1' }, { text: 'Group 2' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeId: 1,
|
||||||
|
activeId2: 1,
|
||||||
|
activeIds: [1, 2],
|
||||||
|
activeIndex: 0,
|
||||||
|
activeIndex2: 0,
|
||||||
|
activeIndex3: 0,
|
||||||
|
activeIndex4: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
items() {
|
||||||
|
return this.t('data');
|
||||||
|
},
|
||||||
|
|
||||||
|
simpleItems() {
|
||||||
|
return this.t('dataSimple');
|
||||||
|
},
|
||||||
|
|
||||||
|
badgeItems() {
|
||||||
|
const data = deepClone(this.t('data')).slice(0, 2);
|
||||||
|
|
||||||
|
data[0].dot = true;
|
||||||
|
data[1].badge = 5;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
128
src-next/tree-select/index.js
Normal file
128
src-next/tree-select/index.js
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
// Utils
|
||||||
|
import { createNamespace, addUnit, isDef } from '../utils';
|
||||||
|
|
||||||
|
// Components
|
||||||
|
import Icon from '../icon';
|
||||||
|
import Sidebar from '../sidebar';
|
||||||
|
import SidebarItem from '../sidebar-item';
|
||||||
|
|
||||||
|
const [createComponent, bem] = createNamespace('tree-select');
|
||||||
|
|
||||||
|
export default createComponent({
|
||||||
|
props: {
|
||||||
|
max: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: Infinity,
|
||||||
|
},
|
||||||
|
items: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 300,
|
||||||
|
},
|
||||||
|
activeId: {
|
||||||
|
type: [Number, String, Array],
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
selectedIcon: {
|
||||||
|
type: String,
|
||||||
|
default: 'success',
|
||||||
|
},
|
||||||
|
mainActiveIndex: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
emits: [
|
||||||
|
'click-nav',
|
||||||
|
'click-item',
|
||||||
|
'update:activeId',
|
||||||
|
'update:mainActiveIndex',
|
||||||
|
],
|
||||||
|
|
||||||
|
setup(props, { emit, slots }) {
|
||||||
|
return function () {
|
||||||
|
const { items, height, activeId, selectedIcon, mainActiveIndex } = props;
|
||||||
|
|
||||||
|
const selectedItem = items[+mainActiveIndex] || {};
|
||||||
|
const subItems = selectedItem.children || [];
|
||||||
|
const isMultiple = Array.isArray(activeId);
|
||||||
|
|
||||||
|
function isActiveItem(id) {
|
||||||
|
return isMultiple ? activeId.indexOf(id) !== -1 : activeId === id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Navs = items.map((item) => (
|
||||||
|
<SidebarItem
|
||||||
|
dot={item.dot}
|
||||||
|
info={isDef(item.badge) ? item.badge : item.info}
|
||||||
|
title={item.text}
|
||||||
|
disabled={item.disabled}
|
||||||
|
class={[bem('nav-item'), item.className]}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
function Content() {
|
||||||
|
if (slots.content) {
|
||||||
|
return slots.content();
|
||||||
|
}
|
||||||
|
|
||||||
|
return subItems.map((item) => (
|
||||||
|
<div
|
||||||
|
key={item.id}
|
||||||
|
class={[
|
||||||
|
'van-ellipsis',
|
||||||
|
bem('item', {
|
||||||
|
active: isActiveItem(item.id),
|
||||||
|
disabled: item.disabled,
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
onClick={() => {
|
||||||
|
if (!item.disabled) {
|
||||||
|
let newActiveId = item.id;
|
||||||
|
if (isMultiple) {
|
||||||
|
newActiveId = activeId.slice();
|
||||||
|
|
||||||
|
const index = newActiveId.indexOf(item.id);
|
||||||
|
|
||||||
|
if (index !== -1) {
|
||||||
|
newActiveId.splice(index, 1);
|
||||||
|
} else if (newActiveId.length < props.max) {
|
||||||
|
newActiveId.push(item.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('update:activeId', newActiveId);
|
||||||
|
emit('click-item', item);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.text}
|
||||||
|
{isActiveItem(item.id) && (
|
||||||
|
<Icon name={selectedIcon} class={bem('selected')} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class={bem()} style={{ height: addUnit(height) }}>
|
||||||
|
<Sidebar
|
||||||
|
class={bem('nav')}
|
||||||
|
modelValue={mainActiveIndex}
|
||||||
|
onChange={(index) => {
|
||||||
|
emit('update:mainActiveIndex', index);
|
||||||
|
emit('click-nav', index);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{Navs}
|
||||||
|
</Sidebar>
|
||||||
|
<div class={bem('content')}>{Content()}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
51
src-next/tree-select/index.less
Normal file
51
src-next/tree-select/index.less
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
@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 {
|
||||||
|
padding: @tree-select-nav-item-padding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
flex: 2;
|
||||||
|
overflow-y: auto;
|
||||||
|
background-color: @tree-select-content-background-color;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
position: relative;
|
||||||
|
padding: 0 32px 0 @padding-md;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
line-height: @tree-select-item-height;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&--active {
|
||||||
|
color: @tree-select-item-active-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--disabled {
|
||||||
|
color: @tree-select-item-disabled-color;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__selected {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: @padding-md;
|
||||||
|
margin-top: -@padding-xs;
|
||||||
|
font-size: @tree-select-item-selected-size;
|
||||||
|
}
|
||||||
|
}
|
90
src-next/tree-select/test/__snapshots__/demo.spec.js.snap
Normal file
90
src-next/tree-select/test/__snapshots__/demo.spec.js.snap
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// 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-sidebar van-tree-select__nav"><a class="van-sidebar-item van-sidebar-item--select van-tree-select__nav-item">
|
||||||
|
<div class="van-sidebar-item__text">浙江
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
</a><a class="van-sidebar-item van-tree-select__nav-item">
|
||||||
|
<div class="van-sidebar-item__text">江苏
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
</a><a class="van-sidebar-item van-sidebar-item--disabled van-tree-select__nav-item">
|
||||||
|
<div class="van-sidebar-item__text">福建
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
</a></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-success van-tree-select__selected">
|
||||||
|
<!----></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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-tree-select" style="height: 300px;">
|
||||||
|
<div class="van-sidebar van-tree-select__nav"><a class="van-sidebar-item van-sidebar-item--select van-tree-select__nav-item">
|
||||||
|
<div class="van-sidebar-item__text">浙江
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
</a><a class="van-sidebar-item van-tree-select__nav-item">
|
||||||
|
<div class="van-sidebar-item__text">江苏
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
</a><a class="van-sidebar-item van-sidebar-item--disabled van-tree-select__nav-item">
|
||||||
|
<div class="van-sidebar-item__text">福建
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
</a></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-success van-tree-select__selected">
|
||||||
|
<!----></i></div>
|
||||||
|
<div class="van-ellipsis van-tree-select__item van-tree-select__item--active">温州<i class="van-icon van-icon-success van-tree-select__selected">
|
||||||
|
<!----></i></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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-tree-select" style="height: 55vw;">
|
||||||
|
<div class="van-sidebar van-tree-select__nav"><a class="van-sidebar-item van-sidebar-item--select van-tree-select__nav-item">
|
||||||
|
<div class="van-sidebar-item__text">分组 1
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
</a><a class="van-sidebar-item van-tree-select__nav-item">
|
||||||
|
<div class="van-sidebar-item__text">分组 2
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
</a></div>
|
||||||
|
<div class="van-tree-select__content">
|
||||||
|
<div class="van-image"><img src="https://img.yzcdn.cn/vant/apple-1.jpg" class="van-image__img"></div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-tree-select" style="height: 55vw;">
|
||||||
|
<div class="van-sidebar van-tree-select__nav"><a class="van-sidebar-item van-sidebar-item--select van-tree-select__nav-item">
|
||||||
|
<div class="van-sidebar-item__text">浙江<div class="van-info van-info--dot van-sidebar-item__info"></div>
|
||||||
|
</div>
|
||||||
|
</a><a class="van-sidebar-item van-tree-select__nav-item">
|
||||||
|
<div class="van-sidebar-item__text">江苏<div class="van-info van-sidebar-item__info">5</div>
|
||||||
|
</div>
|
||||||
|
</a></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-success van-tree-select__selected">
|
||||||
|
<!----></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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
41
src-next/tree-select/test/__snapshots__/index.spec.js.snap
Normal file
41
src-next/tree-select/test/__snapshots__/index.spec.js.snap
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`content slot 1`] = `
|
||||||
|
<div class="van-tree-select" style="height: 300px;">
|
||||||
|
<div class="van-sidebar van-tree-select__nav"><a class="van-sidebar-item van-sidebar-item--select van-tree-select__nav-item">
|
||||||
|
<div class="van-sidebar-item__text">group1
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
</a></div>
|
||||||
|
<div class="van-tree-select__content">Custom Content</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`empty list 1`] = `
|
||||||
|
<div class="van-tree-select" style="height: 300px;">
|
||||||
|
<div class="van-sidebar van-tree-select__nav"></div>
|
||||||
|
<div class="van-tree-select__content"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`height prop 1`] = `
|
||||||
|
<div class="van-tree-select" style="height: 100vh;">
|
||||||
|
<div class="van-sidebar van-tree-select__nav"></div>
|
||||||
|
<div class="van-tree-select__content"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`nav info 1`] = `
|
||||||
|
<div class="van-tree-select" style="height: 300px;">
|
||||||
|
<div class="van-sidebar van-tree-select__nav"><a class="van-sidebar-item van-sidebar-item--select van-tree-select__nav-item">
|
||||||
|
<div class="van-sidebar-item__text">group1<div class="van-info van-sidebar-item__info">3</div>
|
||||||
|
</div>
|
||||||
|
</a></div>
|
||||||
|
<div class="van-tree-select__content"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`selected-icon prop 1`] = `
|
||||||
|
<div class="van-ellipsis van-tree-select__item van-tree-select__item--active">city1<i class="van-icon van-icon-foo van-tree-select__selected">
|
||||||
|
<!----></i></div>
|
||||||
|
`;
|
4
src-next/tree-select/test/demo.spec.js
Normal file
4
src-next/tree-select/test/demo.spec.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import Demo from '../demo';
|
||||||
|
import { snapshotDemo } from '../../../test/demo';
|
||||||
|
|
||||||
|
snapshotDemo(Demo);
|
345
src-next/tree-select/test/index.spec.js
Normal file
345
src-next/tree-select/test/index.spec.js
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
import TreeSelect from '..';
|
||||||
|
import { mount } from '../../../test';
|
||||||
|
|
||||||
|
test('empty list', () => {
|
||||||
|
expect(mount(TreeSelect)).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
const mockItem = {
|
||||||
|
text: 'city1',
|
||||||
|
id: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockItem2 = {
|
||||||
|
text: 'city2',
|
||||||
|
id: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockItems = [
|
||||||
|
{
|
||||||
|
text: 'group1',
|
||||||
|
children: [mockItem],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'group2',
|
||||||
|
children: [mockItem],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
test('click-nav event', () => {
|
||||||
|
const onNavClick = jest.fn();
|
||||||
|
const onClickNav = jest.fn();
|
||||||
|
|
||||||
|
const wrapper = mount(TreeSelect, {
|
||||||
|
propsData: {
|
||||||
|
items: mockItems,
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
on: {
|
||||||
|
navclick: onNavClick,
|
||||||
|
'click-nav': onClickNav,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const navItems = wrapper.findAll('.van-tree-select__nav-item');
|
||||||
|
navItems.at(1).trigger('click');
|
||||||
|
|
||||||
|
expect(onNavClick).toHaveBeenCalledWith(1);
|
||||||
|
expect(onClickNav).toHaveBeenCalledWith(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('click-item event', () => {
|
||||||
|
const onItemClick = jest.fn();
|
||||||
|
const onClickItem = jest.fn();
|
||||||
|
|
||||||
|
const wrapper = mount(TreeSelect, {
|
||||||
|
propsData: {
|
||||||
|
items: mockItems,
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
on: {
|
||||||
|
itemclick: onItemClick,
|
||||||
|
'click-item': onClickItem,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const items = wrapper.findAll('.van-tree-select__item');
|
||||||
|
items.at(0).trigger('click');
|
||||||
|
expect(onItemClick).toHaveBeenCalledWith(mockItem);
|
||||||
|
expect(onClickItem).toHaveBeenCalledWith(mockItem);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('click disabled nav', () => {
|
||||||
|
const onClickNav = jest.fn();
|
||||||
|
|
||||||
|
const wrapper = mount(TreeSelect, {
|
||||||
|
propsData: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'group1',
|
||||||
|
children: [mockItem],
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
on: {
|
||||||
|
'click-nav': onClickNav,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const items = wrapper.findAll('.van-tree-select__nav-item');
|
||||||
|
items.at(0).trigger('click');
|
||||||
|
expect(onClickNav).toHaveBeenCalledTimes(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('click disabled item', () => {
|
||||||
|
const onClickItem = jest.fn();
|
||||||
|
const wrapper = mount(TreeSelect, {
|
||||||
|
propsData: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'group1',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
...mockItem,
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
on: {
|
||||||
|
'click-item': onClickItem,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const items = wrapper.findAll('.van-tree-select__item');
|
||||||
|
items.at(0).trigger('click');
|
||||||
|
expect(onClickItem).toHaveBeenCalledTimes(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('content slot', () => {
|
||||||
|
const wrapper = mount(TreeSelect, {
|
||||||
|
propsData: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'group1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
scopedSlots: {
|
||||||
|
content: () => 'Custom Content',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('height prop', () => {
|
||||||
|
const wrapper = mount(TreeSelect, {
|
||||||
|
propsData: {
|
||||||
|
height: '100vh',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('nav info', () => {
|
||||||
|
const wrapper = mount(TreeSelect, {
|
||||||
|
propsData: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'group1',
|
||||||
|
info: 3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('use sync modifier in main-active-index', () => {
|
||||||
|
const wrapper = mount({
|
||||||
|
template: `
|
||||||
|
<van-tree-select
|
||||||
|
:items="items"
|
||||||
|
:main-active-index.sync="mainActiveIndex"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
mainActiveIndex: -1,
|
||||||
|
items: mockItems,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const navItems = wrapper.findAll('.van-tree-select__nav-item');
|
||||||
|
navItems.at(0).trigger('click');
|
||||||
|
|
||||||
|
expect(wrapper.vm.mainActiveIndex).toEqual(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('use sync modifier in active-id', () => {
|
||||||
|
const wrapper = mount({
|
||||||
|
template: `
|
||||||
|
<van-tree-select
|
||||||
|
:items="items"
|
||||||
|
:main-active-index="0"
|
||||||
|
:active-id.sync="activeId"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeId: mockItem.id,
|
||||||
|
mainActiveIndex: 0,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'group1',
|
||||||
|
children: [mockItem, mockItem2],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const items = wrapper.findAll('.van-tree-select__item');
|
||||||
|
items.at(1).trigger('click');
|
||||||
|
|
||||||
|
expect(wrapper.vm.activeId).toEqual(mockItem2.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('multiple select', () => {
|
||||||
|
const wrapper = mount({
|
||||||
|
template: `
|
||||||
|
<van-tree-select
|
||||||
|
:items="items"
|
||||||
|
:main-active-index="0"
|
||||||
|
:active-id.sync="activeId"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeId: [],
|
||||||
|
mainActiveIndex: 0,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'group1',
|
||||||
|
children: [mockItem, mockItem2],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const items = wrapper.findAll('.van-tree-select__item');
|
||||||
|
items.at(0).trigger('click');
|
||||||
|
items.at(1).trigger('click');
|
||||||
|
expect(wrapper.vm.activeId).toEqual([mockItem.id, mockItem2.id]);
|
||||||
|
|
||||||
|
items.at(0).trigger('click');
|
||||||
|
items.at(1).trigger('click');
|
||||||
|
expect(wrapper.vm.activeId).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('max prop', () => {
|
||||||
|
const wrapper = mount({
|
||||||
|
template: `
|
||||||
|
<van-tree-select
|
||||||
|
:max="1"
|
||||||
|
:items="items"
|
||||||
|
:main-active-index="0"
|
||||||
|
:active-id.sync="activeId"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeId: [],
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'group1',
|
||||||
|
children: [mockItem, mockItem2],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const items = wrapper.findAll('.van-tree-select__item');
|
||||||
|
items.at(0).trigger('click');
|
||||||
|
items.at(1).trigger('click');
|
||||||
|
expect(wrapper.vm.activeId).toEqual([mockItem.id]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('className of nav', () => {
|
||||||
|
const wrapper = mount(TreeSelect, {
|
||||||
|
propsData: {
|
||||||
|
mainActiveIndex: 0,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'group1',
|
||||||
|
className: 'my-class',
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const items = wrapper.findAll('.van-tree-select__nav-item');
|
||||||
|
expect(items.at(0).element.classList.contains('my-class')).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should sync value before trigger click-item event', (done) => {
|
||||||
|
const wrapper = mount({
|
||||||
|
template: `
|
||||||
|
<van-tree-select
|
||||||
|
:items="items"
|
||||||
|
:main-active-index="0"
|
||||||
|
:active-id.sync="activeId"
|
||||||
|
@click-item="onClickItem"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeId: mockItem.id,
|
||||||
|
mainActiveIndex: 0,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'group1',
|
||||||
|
children: [mockItem, mockItem2],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onClickItem() {
|
||||||
|
expect(wrapper.vm.activeId).toEqual(mockItem2.id);
|
||||||
|
done();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const items = wrapper.findAll('.van-tree-select__item');
|
||||||
|
items.at(1).trigger('click');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('selected-icon prop', () => {
|
||||||
|
const wrapper = mount(TreeSelect, {
|
||||||
|
propsData: {
|
||||||
|
items: mockItems,
|
||||||
|
activeId: 1,
|
||||||
|
mainActiveIndex: 0,
|
||||||
|
selectedIcon: 'foo',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.find('.van-tree-select__item')).toMatchSnapshot();
|
||||||
|
});
|
@ -302,10 +302,10 @@ module.exports = {
|
|||||||
path: 'pagination',
|
path: 'pagination',
|
||||||
title: 'Pagination 分页',
|
title: 'Pagination 分页',
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// path: 'sidebar',
|
path: 'sidebar',
|
||||||
// title: 'Sidebar 侧边导航',
|
title: 'Sidebar 侧边导航',
|
||||||
// },
|
},
|
||||||
// {
|
// {
|
||||||
// path: 'tab',
|
// path: 'tab',
|
||||||
// title: 'Tab 标签页',
|
// title: 'Tab 标签页',
|
||||||
@ -314,10 +314,10 @@ module.exports = {
|
|||||||
// path: 'tabbar',
|
// path: 'tabbar',
|
||||||
// title: 'Tabbar 标签栏',
|
// title: 'Tabbar 标签栏',
|
||||||
// },
|
// },
|
||||||
// {
|
{
|
||||||
// path: 'tree-select',
|
path: 'tree-select',
|
||||||
// title: 'TreeSelect 分类选择',
|
title: 'TreeSelect 分类选择',
|
||||||
// },
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -636,10 +636,10 @@ module.exports = {
|
|||||||
path: 'pagination',
|
path: 'pagination',
|
||||||
title: 'Pagination',
|
title: 'Pagination',
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// path: 'sidebar',
|
path: 'sidebar',
|
||||||
// title: 'Sidebar',
|
title: 'Sidebar',
|
||||||
// },
|
},
|
||||||
// {
|
// {
|
||||||
// path: 'tab',
|
// path: 'tab',
|
||||||
// title: 'Tab',
|
// title: 'Tab',
|
||||||
@ -648,10 +648,10 @@ module.exports = {
|
|||||||
// path: 'tabbar',
|
// path: 'tabbar',
|
||||||
// title: 'Tabbar',
|
// title: 'Tabbar',
|
||||||
// },
|
// },
|
||||||
// {
|
{
|
||||||
// path: 'tree-select',
|
path: 'tree-select',
|
||||||
// title: 'TreeSelect',
|
title: 'TreeSelect',
|
||||||
// },
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user