mirror of
https://gitee.com/vant-contrib/vant-weapp.git
synced 2025-04-06 03:58:05 +08:00
[new feature] TreeSelect: 新增分类选择组件 (#346)
* 增加 tree select 组件 * 增加文档 * 增加文档 * update magic code
This commit is contained in:
parent
222084f704
commit
c5fef65228
@ -85,6 +85,11 @@ module.exports = {
|
|||||||
toptips: require('./packages/toptips/README.md'),
|
toptips: require('./packages/toptips/README.md'),
|
||||||
loadmore: require('./packages/loadmore/README.md')
|
loadmore: require('./packages/loadmore/README.md')
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
base: 'complexComponent',
|
||||||
|
label: '高阶组件',
|
||||||
|
include: { tree_select: require('./packages/tree-select/README.md') }
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
include: {}
|
include: {}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
"pages/tag/index",
|
"pages/tag/index",
|
||||||
"pages/toptips/index",
|
"pages/toptips/index",
|
||||||
"pages/toast/index",
|
"pages/toast/index",
|
||||||
|
"pages/tree-select/index",
|
||||||
"pages/select/index",
|
"pages/select/index",
|
||||||
"pages/datetime/index"
|
"pages/datetime/index"
|
||||||
],
|
],
|
||||||
|
30
example/pages/tree-select/config.js
Normal file
30
example/pages/tree-select/config.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
module.exports = {
|
||||||
|
pro1Name: '浙江',
|
||||||
|
pro1: [{
|
||||||
|
text: '杭州',
|
||||||
|
id: 1001
|
||||||
|
}, {
|
||||||
|
text: '温州',
|
||||||
|
id: 1002
|
||||||
|
}, {
|
||||||
|
text: '宁波',
|
||||||
|
id: 1003
|
||||||
|
}, {
|
||||||
|
text: '义乌',
|
||||||
|
id: 1004
|
||||||
|
}],
|
||||||
|
pro2Name: '江苏',
|
||||||
|
pro2: [{
|
||||||
|
text: '无锡',
|
||||||
|
id: 1011
|
||||||
|
}, {
|
||||||
|
text: '常州',
|
||||||
|
id: 1012
|
||||||
|
}, {
|
||||||
|
text: '莆田',
|
||||||
|
id: 1013
|
||||||
|
}, {
|
||||||
|
text: '三明',
|
||||||
|
id: 1014
|
||||||
|
}]
|
||||||
|
};
|
38
example/pages/tree-select/index.js
Normal file
38
example/pages/tree-select/index.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
const config = require('./config');
|
||||||
|
|
||||||
|
Page({
|
||||||
|
data: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
// 导航名称
|
||||||
|
text: '所有城市',
|
||||||
|
// 该导航下所有的可选项
|
||||||
|
children: [ ...config.pro1, ...config.pro2 ]
|
||||||
|
}, {
|
||||||
|
// 导航名称
|
||||||
|
text: config.pro1Name,
|
||||||
|
// 该导航下所有的可选项
|
||||||
|
children: config.pro1
|
||||||
|
}, {
|
||||||
|
text: config.pro2Name,
|
||||||
|
children: config.pro2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
mainActiveIndex: 0,
|
||||||
|
|
||||||
|
activeId: 1002
|
||||||
|
},
|
||||||
|
|
||||||
|
handleNavClick({ detail = {} }) {
|
||||||
|
this.setData({
|
||||||
|
mainActiveIndex: detail.index || 0
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handleItemClick({ detail = {} }) {
|
||||||
|
this.setData({
|
||||||
|
activeId: detail.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
7
example/pages/tree-select/index.json
Normal file
7
example/pages/tree-select/index.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"navigationBarTitleText": "Tree Select 分类选择",
|
||||||
|
"usingComponents": {
|
||||||
|
"zan-tree-select": "../../dist/tree-select/index",
|
||||||
|
"doc-page": "../../components/doc-page/index"
|
||||||
|
}
|
||||||
|
}
|
11
example/pages/tree-select/index.wxml
Normal file
11
example/pages/tree-select/index.wxml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<doc-page title="TREE SELECT" without-padding>
|
||||||
|
<view style="margin-top: 5vh;">
|
||||||
|
<zan-tree-select
|
||||||
|
items="{{ items }}"
|
||||||
|
main-active-index="{{ mainActiveIndex }}"
|
||||||
|
active-id="{{ activeId }}"
|
||||||
|
bind:itemclick="handleItemClick"
|
||||||
|
bind:navclick="handleNavClick"
|
||||||
|
></zan-tree-select>
|
||||||
|
</view>
|
||||||
|
</doc-page>
|
87
packages/tree-select/README.md
Normal file
87
packages/tree-select/README.md
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
## TreeSelect 分类选择
|
||||||
|
|
||||||
|
### 使用指南
|
||||||
|
在 index.json 中引入组件
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"usingComponents": {
|
||||||
|
"zan-tree-select": "path/to/zanui-weapp/dist/tree-select/index"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 代码演示
|
||||||
|
可以在任意位置上使用 zan-tree-select 标签。传入对应的数据即可。
|
||||||
|
```html
|
||||||
|
<zan-tree-select
|
||||||
|
items="{{ items }}"
|
||||||
|
main-active-index="{{ mainActiveIndex }}"
|
||||||
|
active-id="{{ activeId }}"
|
||||||
|
bind:navclick="handleNavClick"
|
||||||
|
bind:itemclick="handleItemClick"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
```javascript
|
||||||
|
Page({
|
||||||
|
data: {
|
||||||
|
// ...
|
||||||
|
},
|
||||||
|
|
||||||
|
handleNavClick({ detail = {} }) {
|
||||||
|
this.setData({
|
||||||
|
mainActiveIndex: detail.index || 0
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handleItemClick({ detail = {} }) {
|
||||||
|
this.setData({
|
||||||
|
activeId: detail.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 | 必须 |
|
||||||
|
|-----------|-----------|-----------|-------------|-------------|
|
||||||
|
| items | 分类显示所需的数据,具体数据结构可看 数据结构 | Array | [] | |
|
||||||
|
| main-active-index | 左侧导航高亮的索引 | Number | 0 | |
|
||||||
|
| active-id | 右侧选择项,高亮的数据id | String | Number | 0 | |
|
||||||
|
|
||||||
|
### Event
|
||||||
|
|
||||||
|
| 事件名称 | 说明 | 回调参数 |
|
||||||
|
|-----------|-----------|-----------|
|
||||||
|
| navclick | 左侧导航点击时,触发的事件 | index:被点击的导航的索引 |
|
||||||
|
| itemclick | 右侧选择项被点击时,会触发的事件 | data: 该点击项的数据 |
|
||||||
|
|
||||||
|
### 数据格式
|
||||||
|
#### items 分类显示所需数据的数据结构
|
||||||
|
`items` 整体为一个数组,数组内包含一系列描述分类的 object。
|
||||||
|
|
||||||
|
每个分类里,text表示当前分类的名称。children 表示分类里的可选项,为数组结构,id被用来唯一标识每个选项
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
[
|
||||||
|
{
|
||||||
|
// 导航名称
|
||||||
|
text: '所有城市',
|
||||||
|
// 该导航下所有的可选项
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
// 可选项的名称
|
||||||
|
text: '温州',
|
||||||
|
// 可选项的id,高亮的时候是根据id是否和选中的id是否相同进行判断的
|
||||||
|
id: 1002
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 可选项的名称
|
||||||
|
text: '杭州',
|
||||||
|
// 可选项的id,高亮的时候是根据id是否和选中的id是否相同进行判断的
|
||||||
|
id: 1001
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
73
packages/tree-select/index.js
Normal file
73
packages/tree-select/index.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
const ITEM_HEIGHT = 44;
|
||||||
|
|
||||||
|
Component({
|
||||||
|
properties: {
|
||||||
|
items: {
|
||||||
|
type: Array,
|
||||||
|
observer() {
|
||||||
|
this.updateSubItems();
|
||||||
|
this.updateMainHeight();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mainActiveIndex: {
|
||||||
|
type: Number,
|
||||||
|
value: 0,
|
||||||
|
observer() {
|
||||||
|
this.updateSubItems();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
activeId: {
|
||||||
|
type: Number,
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
maxHeight: {
|
||||||
|
type: Number,
|
||||||
|
value: 300,
|
||||||
|
observer() {
|
||||||
|
this.updateItemHeight();
|
||||||
|
this.updateMainHeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data: {
|
||||||
|
subItems: [],
|
||||||
|
mainHeight: 0,
|
||||||
|
itemHeight: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
// 当一个子项被选择时
|
||||||
|
onItemSelect({ currentTarget = {} }) {
|
||||||
|
const { dataset: data = {} } = currentTarget;
|
||||||
|
this.triggerEvent('itemclick', { ...(data.item || {}) });
|
||||||
|
},
|
||||||
|
|
||||||
|
// 当一个导航被点击时
|
||||||
|
handleNavClick({ currentTarget = {} }) {
|
||||||
|
const { dataset: data = {} } = currentTarget;
|
||||||
|
this.triggerEvent('navclick', { index: data.index });
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新子项列表
|
||||||
|
updateSubItems() {
|
||||||
|
const selectedItem = this.data.items[this.data.mainActiveIndex] || {};
|
||||||
|
|
||||||
|
this.setData({ subItems: selectedItem.children || [] });
|
||||||
|
|
||||||
|
this.updateItemHeight();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新组件整体高度,根据最大高度和当前组件需要展示的高度来决定
|
||||||
|
updateMainHeight() {
|
||||||
|
const maxHeight = Math.max(this.data.items.length * ITEM_HEIGHT, this.data.subItems.length * ITEM_HEIGHT);
|
||||||
|
|
||||||
|
this.setData({ mainHeight: Math.min(maxHeight, this.data.maxHeight) })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新子项列表高度,根据可展示的最大高度和当前子项列表的高度决定
|
||||||
|
updateItemHeight() {
|
||||||
|
this.setData({ itemHeight: Math.min(this.data.subItems.length * ITEM_HEIGHT, this.data.maxHeight) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
6
packages/tree-select/index.json
Normal file
6
packages/tree-select/index.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"component": true,
|
||||||
|
"usingComponents": {
|
||||||
|
"zan-icon": "../icon/index"
|
||||||
|
}
|
||||||
|
}
|
55
packages/tree-select/index.pcss
Normal file
55
packages/tree-select/index.pcss
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
@import "../helper/index.pcss";
|
||||||
|
|
||||||
|
.tree-select {
|
||||||
|
user-select: none;
|
||||||
|
position: relative;
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
|
&__nav {
|
||||||
|
width: 143px;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
overflow: scroll;
|
||||||
|
background-color: #fff;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__nitem {
|
||||||
|
line-height: 44px;
|
||||||
|
padding: 0 15px;
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
|
&--active {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
padding: 0 15px;
|
||||||
|
margin-left: 143px;
|
||||||
|
overflow: scroll;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
position: relative;
|
||||||
|
line-height: 44px;
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-right: 18px;
|
||||||
|
|
||||||
|
&--active {
|
||||||
|
color: #f44;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__selected {
|
||||||
|
float: right;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
}
|
34
packages/tree-select/index.wxml
Normal file
34
packages/tree-select/index.wxml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<view
|
||||||
|
class="tree-select"
|
||||||
|
style="height: {{ mainHeight }}px"
|
||||||
|
>
|
||||||
|
<view class="tree-select__nav">
|
||||||
|
<view
|
||||||
|
wx:for="{{ items }}"
|
||||||
|
class="tree-select__nitem zan-ellipsis {{ mainActiveIndex === index ? 'tree-select__nitem--active' : '' }}"
|
||||||
|
data-index="{{ index }}"
|
||||||
|
bindtap="handleNavClick"
|
||||||
|
>
|
||||||
|
{{ item.text }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="tree-select__content"
|
||||||
|
style="height: {{ itemHeight }}px"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
wx:for="{{ subItems }}"
|
||||||
|
wx:key="id"
|
||||||
|
class="tree-select__item zan-ellipsis {{ activeId === item.id ? 'tree-select__item--active' : '' }}"
|
||||||
|
data-item="{{ item }}"
|
||||||
|
bindtap="onItemSelect"
|
||||||
|
>
|
||||||
|
{{ item.text }}
|
||||||
|
<zan-icon
|
||||||
|
wx:if="{{ activeId === item.id }}"
|
||||||
|
type="success"
|
||||||
|
class="tree-select__selected"
|
||||||
|
></zan-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
Loading…
x
Reference in New Issue
Block a user