1
0
mirror of https://gitee.com/vant-contrib/vant-weapp.git synced 2025-04-06 03:58:05 +08:00

feat(Collapse): add new component Collapse @rex-zsd ()

This commit is contained in:
rex 2018-11-23 23:29:32 +08:00 committed by neverland
parent 902f4d4368
commit 559dde9616
17 changed files with 454 additions and 8 deletions

@ -49,7 +49,8 @@ const MAP = {
transition: 'transition-20180821.png',
'tree-select': 'tree-select-201808092138.png',
checkbox: 'checkbox-20181110.jpeg',
rate: 'rate-20181120-1.png'
rate: 'rate-20181120-1.png',
collapse: 'collapse-20181123.png'
};
export default {

@ -36,7 +36,8 @@
"pages/goods-action/index",
"pages/swipe-cell/index",
"pages/datetime-picker/index",
"pages/rate/index"
"pages/rate/index",
"pages/collapse/index"
],
"window": {
"navigationBarBackgroundColor": "#f8f8f8",
@ -91,6 +92,8 @@
"van-transition": "../../dist/transition/index",
"van-tree-select": "../../dist/tree-select/index",
"van-datetime-picker": "../../dist/datetime-picker/index",
"van-rate": "../../dist/rate/index"
"van-rate": "../../dist/rate/index",
"van-collapse": "../../dist/collapse/index",
"van-collapse-item": "../../dist/collapse-item/index"
}
}

@ -109,6 +109,10 @@ export default [
path: '/notice-bar',
title: 'NoticeBar 通告栏'
},
{
path: '/collapse',
title: 'Collapse 折叠面板'
},
{
path: '/panel',
title: 'Panel 面板'

@ -0,0 +1,21 @@
import Page from '../../common/page';
Page({
data: {
active1: [0],
active2: 0,
active3: [],
title1: '有赞微商城',
title2: '有赞零售',
title3: '有赞美业',
content1: '提供多样店铺模板,快速搭建网上商城',
content2: '网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失',
content3: '线上拓客,随时预约,贴心顺手的开单收银'
},
onChange(event) {
const { key } = event.currentTarget.dataset;
this.setData({
[key]: event.detail
});
}
});

@ -0,0 +1,3 @@
{
"navigationBarTitleText": "Collapse 折叠面板"
}

@ -0,0 +1,37 @@
<demo-block title="基础用法">
<van-collapse value="{{ active1 }}" data-key="active1" bind:change="onChange">
<van-collapse-item title="{{ title1 }}" content-class="van-collapse-item__content">{{ content1 }}</van-collapse-item>
<van-collapse-item title="{{ title2 }}" content-class="van-collapse-item__content">{{ content2 }}</van-collapse-item>
<van-collapse-item
title="{{ title3 }}"
content-class="van-collapse-item__content"
disabled
>
{{ content3 }}
</van-collapse-item>
</van-collapse>
</demo-block>
<demo-block title="手风琴">
<van-collapse value="{{ active2 }}" data-key="active2" accordion bind:change="onChange">
<van-collapse-item title="{{ title1 }}" content-class="van-collapse-item__content">{{ content1 }}</van-collapse-item>
<van-collapse-item title="{{ title2 }}" content-class="van-collapse-item__content">{{ content2 }}</van-collapse-item>
<van-collapse-item title="{{ title3 }}" content-class="van-collapse-item__content">{{ content3 }}</van-collapse-item>
</van-collapse>
</demo-block>
<demo-block title="自定义标题内容">
<van-collapse value="{{ active3 }}" data-key="active3" bind:change="onChange">
<van-collapse-item content-class="van-collapse-item__content">
<view slot="title">{{ title1 }}<van-icon name="question" custom-class="van-icon-question" /></view>
{{ content1 }}
</van-collapse-item>
<van-collapse-item
title="{{ title2 }}"
content-class="van-collapse-item__content"
value="内容"
icon="shop"
>{{ content2 }}</van-collapse-item>
<van-collapse-item title="{{ title3 }}" content-class="van-collapse-item__content">{{ content3 }}</van-collapse-item>
</van-collapse>
</demo-block>

@ -0,0 +1,12 @@
.van-collapse-item__content {
font-size: 13px;
line-height: 1.5;
color: #666;
}
.van-icon-question {
margin-left: 5px;
font-size: 15px !important;
color: #1989fa;
vertical-align: -3px;
}

@ -54,10 +54,13 @@
&__left-icon-wrap {
margin-right: 5px;
font-size: 16px;
}
&__right-icon-wrap {
margin-left: 5px;
font-size: 12px;
color: @gray-dark;
&--left {
transform: rotate(180deg);
@ -73,14 +76,11 @@
}
&__left-icon {
font-size: 16px !important;
line-height: 24px;
vertical-align: middle;
}
&__right-icon {
color: @gray-dark;
font-size: 12px !important;
line-height: 24px;
}

@ -5,7 +5,8 @@ VantComponent({
classes: [
'title-class',
'label-class',
'value-class'
'value-class',
'right-icon-class'
],
mixins: [link],
@ -47,7 +48,7 @@ VantComponent({
},
iconWrapClass(): string {
const prefix = 'van-cell__right-icon-wrap';
const prefix = 'van-cell__right-icon-wrap right-icon-class';
return this.classNames(prefix, `${prefix}--${this.data.arrowDirection}`);
}
},

@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index"
}
}

@ -0,0 +1,38 @@
@import '../common/style/var.less';
.van-collapse-item {
&__title {
.van-cell__right-icon {
transform: rotate(90deg);
transition: 0.3s;
}
&--expanded {
.van-cell__right-icon {
transform: rotate(-90deg);
}
}
&--disabled {
& .van-cell,
& .van-cell__right-icon {
color: @gray !important;
}
&:active {
background-color: @white !important;
}
}
}
&__wrapper {
overflow: hidden;
will-change: max-height;
transition: max-height 0.3s ease-in-out;
}
&__content {
padding: 15px;
background-color: @white;
}
}

@ -0,0 +1,96 @@
import { VantComponent } from '../common/component';
VantComponent({
classes: ['content-class'],
relation: {
name: 'collapse',
type: 'ancestor',
linked(parent: Weapp.Component) {
this.parent = parent;
}
},
props: {
name: [String, Number],
icon: String,
label: String,
title: [String, Number],
value: [String, Number],
disabled: Boolean,
border: {
type: Boolean,
value: true
},
isLink: {
type: Boolean,
value: true
}
},
data: {
contentHeight: 0,
expanded: false
},
computed: {
titleClass() {
const { disabled, expanded } = this.data;
return this.classNames('van-collapse-item__title', {
'van-collapse-item__title--disabled': disabled,
'van-collapse-item__title--expanded': expanded
});
}
},
methods: {
updateExpanded() {
if (!this.parent) {
return null;
}
const { value, accordion, items } = this.parent.data;
const { name } = this.data;
const index = items.indexOf(this);
const currentName = name == null ? index : name;
const expanded = accordion
? value === currentName
: value.some(name => name === currentName);
if (expanded !== this.data.expanded) {
this.updateStyle(expanded);
}
this.setData({ expanded });
},
updateStyle(expanded) {
if (expanded) {
this.getRect('.van-collapse-item__content').then(res => {
this.setData({
contentHeight: res.height ? res.height + 'px' : null
});
});
} else {
this.setData({
contentHeight: 0
});
}
},
onClick() {
if (this.data.disabled) {
return;
}
const { name, expanded } = this.data;
const index = this.parent.data.items.indexOf(this);
const currentName = name == null ? index : name;
this.parent.switch(currentName, !expanded);
}
}
});

@ -0,0 +1,39 @@
<view class="van-collapse-item van-hairline--top custom-class">
<van-cell
title="{{ title }}"
icon="{{ icon }}"
is-link="{{ isLink }}"
value="{{ value }}"
label="{{ label }}"
border="{{ border && expanded }}"
class="{{ titleClass }}"
right-icon-class="van-cell__right-icon"
custom-class="van-cell"
arrow-direction="{{ expanded ? 'up' : 'down' }}"
bind:click="onClick"
>
<slot
name="title"
slot="title"
/>
<slot
name="icon"
slot="icon"
/>
<slot name="value" />
<slot
name="right-icon"
slot="right-icon"
/>
</van-cell>
<view
class="van-collapse-item__wrapper"
style="max-height: {{ contentHeight }};"
>
<view
class="van-collapse-item__content content-class"
>
<slot />
</view>
</view>
</view>

127
packages/collapse/README.md Normal file

@ -0,0 +1,127 @@
## Collapse 折叠面板
### 使用指南
在 app.json 或 index.json 中引入组件
```json
"usingComponents": {
"van-collapse": "path/to/vant-weapp/dist/collapse/index",
"van-collapse-item": "path/to/vant-weapp/dist/collapse-item/index"
}
```
### 代码演示
#### 基础用法
通过`value`控制展开的面板列表,`activeNames`为数组格式
```html
<van-collapse value="{{ activeNames }}">
<van-collapse-item title="有赞微商城" name="1">
提供多样店铺模板,快速搭建网上商城
</van-collapse-item>
<van-collapse-item title="有赞零售" name="2">
网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失
</van-collapse-item>
<van-collapse-item title="有赞美业" name="3" disabled>
线上拓客,随时预约,贴心顺手的开单收银
</van-collapse-item>
</van-collapse>
```
``` javascript
Page({
data: {
activeNames: ['1']
}
});
```
#### 手风琴
通过`accordion`可以设置为手风琴模式,最多展开一个面板,此时`activeName`为字符串格式
```html
<van-collapse value="{{ activeName }}" accordion>
<van-collapse-item title="有赞微商城" name="1">
提供多样店铺模板,快速搭建网上商城
</van-collapse-item>
<van-collapse-item title="有赞零售" name="2">
网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失
</van-collapse-item>
<van-collapse-item title="有赞美业" name="3">
线上拓客,随时预约,贴心顺手的开单收银
</van-collapse-item>
</van-collapse>
```
``` javascript
Page({
data: {
activeName: '1'
}
});
```
#### 自定义标题内容
```html
<van-collapse value="{{ activeNames }}">
<van-collapse-item name="1">
<view slot="title">有赞微商城<van-icon name="question" /></view>
提供多样店铺模板,快速搭建网上商城
</van-collapse-item>
<van-collapse-item title="有赞零售" name="2">
网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失
</van-collapse-item>
</van-collapse>
```
### Collapse API
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|------|------|------|------|------|
| value | 当前展开面板的 name | `Array | String | Number` | - |
| accordion | 是否开启手风琴模式 | `Boolean` | `false` |
### Collapse Event
| 事件名 | 说明 | 参数 |
|------|------|------|
| change | 切换面板时触发 | activeNames: `String | Array` |
### CollapseItem API
| 参数 | 说明 | 类型 | 默认值 |
|------|------|------|------|------|
| name | 唯一标识符,默认为索引值 | `String | Number` | `index` |
| title | 标题栏左侧内容 | `String | Number` | - |
| icon | 标题栏左侧图标,可选值见 Icon 组件 | `String` | - |
| value | 标题栏右侧内容 | `String | Number` | - |
| label | 标题栏描述信息 | `String` | - |
| border | 是否显示内边框 | `Boolean` | `true` |
| is-link | 是否展示标题栏右侧箭头并开启点击反馈 | `Boolean` | `true` |
| disabled | 是否禁用面板 | `Boolean` | `false` |
### CollapseItem Slot
| 名称 | 说明 |
|------|------|
| - | 面板内容 |
| value | 自定义显示内容 |
| icon | 自定义`icon` |
| title | 自定义`title` |
| right-icon | 自定义右侧按钮,默认是`arrow` |
### Collapse 外部样式类
| 类名 | 说明 |
|-----------|-----------|
| custom-class | 根节点样式类 |
### CollapseItem 外部样式类
| 类名 | 说明 |
|-----------|-----------|
| custom-class | 根节点样式类 |
| content-class | 内容样式类 |

@ -0,0 +1,3 @@
{
"component": true
}

@ -0,0 +1,52 @@
import { VantComponent } from '../common/component';
VantComponent({
relation: {
name: 'collapse-item',
type: 'descendant',
linked(child: Weapp.Component) {
this.setData({
items: [...this.data.items, child]
}, () => {
child.updateExpanded();
});
}
},
props: {
accordion: Boolean,
value: null
},
data: {
items: []
},
watch: {
value() {
this.data.items.forEach(child => {
child.updateExpanded();
});
},
accordion() {
this.data.items.forEach(child => {
child.updateExpanded();
});
}
},
methods: {
switch(name, expanded) {
const { accordion, value } = this.data;
if (!accordion) {
name = expanded
? value.concat(name)
: value.filter(activeName => activeName !== name);
} else {
name = expanded ? name : '';
}
this.$emit('change', name);
this.$emit('input', name);
}
}
});

@ -0,0 +1,3 @@
<view class="van-collapse van-hairline--top-bottom custom-class">
<slot />
</view>