[breaking change] Actionsheet: rewrite

This commit is contained in:
陈嘉涵 2018-08-06 11:22:42 +08:00
parent 6a52751ff5
commit 1e828d2257
9 changed files with 255 additions and 256 deletions

View File

@ -1,57 +1,36 @@
Page({ Page({
data: { data: {
show: false, show1: false,
cancelWithMask: true, show2: false,
actions: [{ show3: false
name: '选项1',
subname: '选项描述语1',
className: 'action-class',
loading: false
}, {
name: '选项2',
subname: '选项描述语2',
className: 'action-class',
loading: false
}, {
name: '去分享',
openType: 'share'
}],
cancelText: '关闭 Action'
}, },
onShareAppMessage() { onLoad() {
return {
title: 'vant-weapp',
imageUrl: 'https://img.yzcdn.cn/public_files/2017/02/06/ee0ebced79a80457d77ce71c7d414c74.png'
};
},
openActionsheet() {
this.setData({ this.setData({
'show': true actions: [
{ name: '选项' },
{ name: '选项', subname: '禁用' },
{ name: '选项', loading: true },
{ name: '禁用选项', disabled: true }
]
}); });
}, },
closeActionSheet() { toggle(type) {
this.setData({ this.setData({
'show': false [type]: !this.data[type]
}); });
}, },
clickAction({ detail }) { toggleActionsheet1() {
// 如果是分享按钮被点击, 不处理关闭 this.toggle('show1');
const { index } = detail; },
if (index === 2) {
return; toggleActionsheet2() {
} this.toggle('show2');
this.setData({ },
[`actions[${index}].loading`]: true
}); toggleActionsheet3() {
setTimeout(() => { this.toggle('show3');
this.setData({
[`show`]: false,
[`actions[${index}].loading`]: false
});
}, 1500);
} }
}); });

View File

@ -1,6 +1,7 @@
{ {
"navigationBarTitleText": "Actionsheet 上拉菜单", "navigationBarTitleText": "Actionsheet 上拉菜单",
"usingComponents": { "usingComponents": {
"demo-block": "../../components/demo-block/index",
"van-actionsheet": "../../dist/actionsheet/index", "van-actionsheet": "../../dist/actionsheet/index",
"van-button": "../../dist/button/index" "van-button": "../../dist/button/index"
} }

View File

@ -1,15 +1,32 @@
<view class="van-buttons" style="margin-top: 30vh;"> <demo-block title="基础用法" padding>
<van-button bind:tap="openActionsheet"> <van-button bind:tap="toggleActionsheet1">弹出 Actionsheet</van-button>
Actionsheet <van-actionsheet
</van-button> show="{{ show1 }}"
</view>
<van-actionsheet
show="{{ show }}"
actions="{{ actions }}" actions="{{ actions }}"
cancel-text="{{ cancelText }}" bind:close="toggleActionsheet1"
cancel-with-mask="{{ cancelWithMask }}" bind:select="toggleActionsheet1"
bind:cancel="closeActionSheet" />
bind:actionclick="clickAction" </demo-block>
mask-class="tiny"
/> <demo-block title="带取消按钮的 Actionsheet" padding>
<van-button bind:tap="toggleActionsheet2">弹出带取消按钮的 Actionsheet</van-button>
<van-actionsheet
show="{{ show2 }}"
actions="{{ actions }}"
cancel-text="取消"
bind:close="toggleActionsheet2"
bind:cancel="toggleActionsheet2"
bind:select="toggleActionsheet2"
/>
</demo-block>
<demo-block title="带标题的 Actionsheet" padding>
<van-button bind:tap="toggleActionsheet3">弹出带标题的 Actionsheet</van-button>
<van-actionsheet
show="{{ show3 }}"
title="标题"
bind:close="toggleActionsheet3"
>
<view class="content">内容</view>
</van-actionsheet>
</demo-block>

View File

@ -1,3 +1,3 @@
.tiny { .content {
background: rgba(30, 30, 40, 0.7) !important; padding: 20px;
} }

View File

@ -3,92 +3,111 @@
### 使用指南 ### 使用指南
在 index.json 中引入组件 在 index.json 中引入组件
```json ```json
{ "usingComponents": {
"usingComponents": {
"van-actionsheet": "path/to/vant-weapp/dist/actionsheet/index" "van-actionsheet": "path/to/vant-weapp/dist/actionsheet/index"
}
} }
``` ```
### 使用指南 ### 代码演示
#### 基础用法
需要传入一个`actions`的数组,数组的每一项是一个对象,对象属性见文档下方表格。
```html ```html
<button bindtap="openActionSheet">Open ActionSheet</button> <van-actionsheet
<view class="actionsheet-container">
<!-- 监听自定义事件 cancel 和 actionclick绑定回调函数 -->
<van-actionsheet
show="{{ show }}" show="{{ show }}"
actions="{{ actions }}" actions="{{ actions }}"
cancel-text="{{ cancelText }}" bind:close="onClose"
cancel-with-mask="{{ cancelWithMask }}" bind:select="onSelect"
bind:cancel="closeActionSheet" />
bind:actionclick="handleActionClick"
>
</van-actionsheet>
</view>
``` ```
```js ```javascript
// 在 Page 中混入 Actionsheet 里面声明的方法
Page({ Page({
data: { data() {
return {
show: false, show: false,
cancelWithMask: true, actions: [
actions: [{ {
name: '选项1', name: '选项'
subname: '选项描述语1',
loading: false
}, {
name: '选项2',
subname: '选项描述语2',
loading: false
}, {
name: '去分享',
openType: 'share'
}],
cancelText: '关闭 Action'
}, },
openActionSheet() { {
this.setData({ name: '选项',
'show': true subname: '描述信息'
});
}, },
closeActionSheet() { {
this.setData({ name: '选项',
'show': false loading: true
});
}, },
handleActionClick({ detail }) { {
// 获取被点击的按钮 index name: '禁用选项',
const { index } = detail; disabled: true
}
]
};
},
methods: {
onClose() {
this.setData({ show: false });
},
onSelect(event) {
console.log(event.detail);
}
} }
}); });
``` ```
#### 带取消按钮的 Actionsheet
#### `Actionsheet` 支持的具体参数如下( 传入时使用分隔线写法 如果传入了`cancelText`属性,且不为空,则会在下方显示一个取消按钮,点击会将当前`Actionsheet`关闭。
| 参数 | 说明 | 类型 | 默认值 | 必须 |
|-----------|-----------|-----------|-------------|-------------|
| show | 用来表示是否展示上拉菜单 | Boolean | false | |
| actions | 指定弹层里的按钮 | Array | [] | |
| cancelText | 上拉菜单底部取消按钮的文案,不传则不显示取消按钮 | String | | |
| cancelWithMask | 是否在点击背景时,关闭上拉菜单 | Boolean | false | |
| mask-class | 用于控制蒙层样式的外部类 | String | | |
| container-class | 用于控制容器样式的外部类 | String | | |
actions 的具体数据结构 ```html
```js <van-actionsheet
// actions 为数组结构传入 show="{{ show }}"
[{ actions="{{ actions }}"
// 按钮文案 cancel-text="取消"
name: '选项1', bind:close="onClose"
// 按钮描述文案,不传就不显示 />
subname: '选项描述语1',
// 按钮是否显示为 loading
loading: false,
// 按钮的微信开放能力
// 具体支持可参考微信官方文档https://mp.weixin.qq.com/debug/wxadoc/dev/component/button.html
openType: 'share'
}]
``` ```
#### 带标题的 Actionsheet
如果传入了`title`属性,且不为空,则另外一种样式的`Actionsheet`,里面内容需要自定义。
```html
<van-actionsheet show="{{ show }}" title="支持以下配送方式">
<view>一些内容</view>
</van-actionsheet>
```
### API
| 参数 | 说明 | 类型 | 默认值 |
|-----------|-----------|-----------|-------------|
| actions | 菜单选项 | `Array` | `[]` |
| title | 标题 | `String` | - |
| cancel-text | 取消按钮文字 | `String` | - |
| overlay | 是否显示遮罩层 | `Boolean` | - |
| close-on-click-overlay | 点击遮罩是否关闭菜单 | `Boolean` | - |
### Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| close | 关闭时触发 | - |
| cancel | 取消按钮点击时触发 | - |
| select | 选中选项时触发,选项禁用或加载时不会触发 | event.detail: 选项对应的对象 |
### actions
`API`中的`actions`为一个对象数组,数组中的每一个对象配置每一列,每一列有以下`key`
| key | 说明 |
|-----------|-----------|
| name | 标题 |
| subname | 二级标题 |
| className | 为对应列添加额外的 class |
| loading | 是否为加载状态 |
| disabled | 是否为禁用状态 |

View File

@ -1,36 +1,39 @@
Component({ Component({
externalClasses: ['mask-class', 'container-class'], externalClasses: ['mask-class', 'container-class'],
properties: { properties: {
show: Boolean,
title: String,
cancelText: String,
actions: { actions: {
type: Array, type: Array,
value: [] value: []
}, },
show: { overlay: {
type: Boolean,
value: false
},
cancelWithMask: {
type: Boolean, type: Boolean,
value: true value: true
}, },
cancelText: { closeOnClickOverlay: {
type: String, type: Boolean,
value: '' value: true
} }
}, },
methods: { methods: {
onMaskClick() { onSelect(event) {
if (this.data.cancelWithMask) { const { index } = event.currentTarget.dataset;
this.cancelClick(); const item = this.data.actions[index];
if (item && !item.disabled && !item.loading) {
this.triggerEvent('select', item);
} }
}, },
cancelClick() {
onCancel() {
this.triggerEvent('cancel'); this.triggerEvent('cancel');
}, },
handleBtnClick({ currentTarget = {} }) {
const dataset = currentTarget.dataset || {}; onClose() {
const { index } = dataset; this.triggerEvent('close');
this.triggerEvent('actionclick', { index });
} }
} }
}); });

View File

@ -1,6 +1,8 @@
{ {
"component": true, "component": true,
"usingComponents": { "usingComponents": {
"van-button": "../button/index" "van-icon": "../icon/index",
"van-popup": "../popup/index",
"van-loading": "../loading/index"
} }
} }

View File

@ -1,85 +1,64 @@
@import "../common/index.pcss"; @import '../common/index.pcss';
.van-actionsheet { .van-actionsheet {
background-color: #f8f8f8; color: $text-color;
} max-height: 90%;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
background-color: $background-color;
.van-actionsheet__mask { &--withtitle {
position: fixed; background-color: $white;
}
&__item,
&__cancel {
height: 50px;
line-height: 50px;
font-size: 16px;
text-align: center;
background-color: $white;
&:active {
background-color: $active-color;
}
}
&__item--disabled {
color: $gray;
&:active {
background-color: $white;
}
}
&__subname {
font-size: 12px;
color: $gray-darker;
margin-left: 5px;
}
&__loading {
display: inline-block;
}
&__cancel {
margin-top: 10px;
}
&__header {
font-size: 16px;
line-height: 44px;
text-align: center;
}
&__close {
top: 0; top: 0;
left: 0;
right: 0; right: 0;
bottom: 0; padding: 0 15px;
z-index: 10; font-size: 18px;
background: rgba(0, 0, 0, 0.7);
display: none;
}
.van-actionsheet__container {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: $background-color;
transform: translate3d(0, 50%, 0);
transform-origin: center;
transition: all 0.2s ease;
z-index: 11;
opacity: 0;
visibility: hidden;
}
.van-actionsheet__button {
margin-bottom: 0 !important;
}
.van-actionsheet__footer .van-actionsheet__button {
background: #fff;
}
.van-actionsheet__button-content {
display: flex;
flex-direction: row;
justify-content: center;
}
.van-actionsheet__subname {
color: $gray-dark; color: $gray-dark;
} position: absolute;
line-height: inherit;
.van-actionsheet__subname,
.van-actionsheet__name {
height: 45px;
line-height: 45px;
}
.van-actionsheet__button.van-button:last-child {
&::after {
border-bottom-width: 0;
} }
} }
.van-actionsheet__subname {
margin-left: 2px;
font-size: 12px;
}
.van-actionsheet__footer {
margin-top: 10px;
}
/* button-loading 状态 */
.van-actionsheet__button--loading .van-actionsheet__subname {
color: transparent;
}
/* van-actionsheet 展示出来的样式 */
.van-actionsheet--show .van-actionsheet__container {
opacity: 1;
transform: translate3d(0, 0, 0);
visibility: visible;
}
.van-actionsheet--show .van-actionsheet__mask {
display: block;
}

View File

@ -1,39 +1,38 @@
<view class="van-actionsheet {{ show ? 'van-actionsheet--show' : '' }}"> <van-popup
show="{{ show }}"
overlay="{{ overlay }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
custom-class="van-actionsheet {{ title ? 'van-actionsheet--withtitle' : '' }}"
position="bottom"
bind:close="onClose"
>
<view wx:if="{{ title }}" class="van-hairline--top-bottom van-actionsheet__header">
<view>{{ title }}</view>
<van-icon custom-class="van-actionsheet__close" name="close" bind:tap="onClose" />
</view>
<view wx:else class="van-hairline--bottom">
<view <view
class="mask-class van-actionsheet__mask"
bindtap="onMaskClick"
></view>
<view class="container-class van-actionsheet__container">
<!-- 选项按钮 -->
<van-button
wx:for="{{ actions }}" wx:for="{{ actions }}"
wx:key="{{ index }}-{{ item.name }}" wx:key="index"
bind:tap="handleBtnClick" class="van-actionsheet__item van-hairline--top {{ item.disabled || item.loading ? 'van-actionsheet__item--disabled' : '' }} {{ item.className || '' }}"
data-index="{{ index }}" data-index="{{ index }}"
open-type="{{ item.openType }}" bind:tap="onSelect"
custom-class="van-actionsheet__button"
loading="{{ item.loading }}"
> >
<!-- 自定义组件控制 slot 样式有问题,故在 slot 容器上传入 loading 信息 --> <block wx:if="{{ !item.loading }}">
<view class="van-actionsheet__button-content {{ item.loading ? 'van-actionsheet__button--loading' : '' }}">
<view class="van-actionsheet__name">{{ item.name }}</view> <view class="van-actionsheet__name">{{ item.name }}</view>
<view <view class="van-actionsheet__subname" wx:if="{{ item.subname }}">{{ item.subname }}</view>
wx:if="{{ item.subname }}" </block>
class="van-actionsheet__subname"> <van-loading wx:else custom-class="van-actionsheet__loading" size="20px" />
{{ item.subname }}
</view> </view>
</view> </view>
</van-button>
<!-- 关闭按钮 -->
<view <view
wx:if="{{ cancelText }}" wx:if="{{ cancelText }}"
class="van-actionsheet__footer" class="van-actionsheet__cancel van-hairline--top"
bind:tap="onCancel"
> >
<van-button {{ cancelText }}
custom-class="van-actionsheet__button"
catchtap="cancelClick"
>{{ cancelText }}</van-button>
</view> </view>
<view wx:else class="van-actionsheet__content">
<slot />
</view> </view>
</view> </van-popup>