[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> actions="{{ actions }}"
bind:close="toggleActionsheet1"
bind:select="toggleActionsheet1"
/>
</demo-block>
<van-actionsheet <demo-block title="带取消按钮的 Actionsheet" padding>
show="{{ show }}" <van-button bind:tap="toggleActionsheet2">弹出带取消按钮的 Actionsheet</van-button>
actions="{{ actions }}" <van-actionsheet
cancel-text="{{ cancelText }}" show="{{ show2 }}"
cancel-with-mask="{{ cancelWithMask }}" actions="{{ actions }}"
bind:cancel="closeActionSheet" cancel-text="取消"
bind:actionclick="clickAction" bind:close="toggleActionsheet2"
mask-class="tiny" 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"> show="{{ show }}"
<!-- 监听自定义事件 cancel 和 actionclick绑定回调函数 --> actions="{{ actions }}"
<van-actionsheet bind:close="onClose"
show="{{ show }}" bind:select="onSelect"
actions="{{ actions }}" />
cancel-text="{{ cancelText }}"
cancel-with-mask="{{ cancelWithMask }}"
bind:cancel="closeActionSheet"
bind:actionclick="handleActionClick"
>
</van-actionsheet>
</view>
``` ```
```js ```javascript
// 在 Page 中混入 Actionsheet 里面声明的方法
Page({ Page({
data: { data() {
show: false, return {
cancelWithMask: true, show: false,
actions: [{ actions: [
name: '选项1', {
subname: '选项描述语1', name: '选项'
loading: false },
}, { {
name: '选项2', name: '选项',
subname: '选项描述语2', subname: '描述信息'
loading: false },
}, { {
name: '去分享', name: '选项',
openType: 'share' loading: true
}], },
cancelText: '关闭 Action' {
name: '禁用选项',
disabled: true
}
]
};
}, },
openActionSheet() {
this.setData({ methods: {
'show': true onClose() {
}); this.setData({ show: false });
}, },
closeActionSheet() {
this.setData({ onSelect(event) {
'show': false console.log(event.detail);
}); }
},
handleActionClick({ detail }) {
// 获取被点击的按钮 index
const { index } = 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;
top: 0; }
left: 0;
right: 0;
bottom: 0;
z-index: 10;
background: rgba(0, 0, 0, 0.7);
display: none;
}
.van-actionsheet__container { &__item,
position: fixed; &__cancel {
left: 0; height: 50px;
right: 0; line-height: 50px;
bottom: 0; font-size: 16px;
background: $background-color; text-align: center;
transform: translate3d(0, 50%, 0); background-color: $white;
transform-origin: center;
transition: all 0.2s ease;
z-index: 11;
opacity: 0;
visibility: hidden;
}
.van-actionsheet__button { &:active {
margin-bottom: 0 !important; background-color: $active-color;
} }
}
.van-actionsheet__footer .van-actionsheet__button { &__item--disabled {
background: #fff; color: $gray;
}
.van-actionsheet__button-content { &:active {
display: flex; background-color: $white;
flex-direction: row; }
justify-content: center; }
}
.van-actionsheet__subname { &__subname {
color: $gray-dark; font-size: 12px;
} color: $gray-darker;
margin-left: 5px;
}
.van-actionsheet__subname, &__loading {
.van-actionsheet__name { display: inline-block;
height: 45px; }
line-height: 45px;
}
&__cancel {
margin-top: 10px;
}
.van-actionsheet__button.van-button:last-child { &__header {
&::after { font-size: 16px;
border-bottom-width: 0; line-height: 44px;
text-align: center;
}
&__close {
top: 0;
right: 0;
padding: 0 15px;
font-size: 18px;
color: $gray-dark;
position: absolute;
line-height: inherit;
} }
} }
.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
<view show="{{ show }}"
class="mask-class van-actionsheet__mask" overlay="{{ overlay }}"
bindtap="onMaskClick" close-on-click-overlay="{{ closeOnClickOverlay }}"
></view> custom-class="van-actionsheet {{ title ? 'van-actionsheet--withtitle' : '' }}"
<view class="container-class van-actionsheet__container"> position="bottom"
<!-- 选项按钮 --> bind:close="onClose"
<van-button >
wx:for="{{ actions }}" <view wx:if="{{ title }}" class="van-hairline--top-bottom van-actionsheet__header">
wx:key="{{ index }}-{{ item.name }}" <view>{{ title }}</view>
bind:tap="handleBtnClick" <van-icon custom-class="van-actionsheet__close" name="close" bind:tap="onClose" />
data-index="{{ index }}" </view>
open-type="{{ item.openType }}" <view wx:else class="van-hairline--bottom">
custom-class="van-actionsheet__button"
loading="{{ item.loading }}"
>
<!-- 自定义组件控制 slot 样式有问题,故在 slot 容器上传入 loading 信息 -->
<view class="van-actionsheet__button-content {{ item.loading ? 'van-actionsheet__button--loading' : '' }}">
<view class="van-actionsheet__name">{{ item.name }}</view>
<view
wx:if="{{ item.subname }}"
class="van-actionsheet__subname">
{{ item.subname }}
</view>
</view>
</van-button>
<!-- 关闭按钮 -->
<view <view
wx:if="{{ cancelText }}" wx:for="{{ actions }}"
class="van-actionsheet__footer" wx:key="index"
class="van-actionsheet__item van-hairline--top {{ item.disabled || item.loading ? 'van-actionsheet__item--disabled' : '' }} {{ item.className || '' }}"
data-index="{{ index }}"
bind:tap="onSelect"
> >
<van-button <block wx:if="{{ !item.loading }}">
custom-class="van-actionsheet__button" <view class="van-actionsheet__name">{{ item.name }}</view>
catchtap="cancelClick" <view class="van-actionsheet__subname" wx:if="{{ item.subname }}">{{ item.subname }}</view>
>{{ cancelText }}</van-button> </block>
<van-loading wx:else custom-class="van-actionsheet__loading" size="20px" />
</view> </view>
</view> </view>
</view> <view
wx:if="{{ cancelText }}"
class="van-actionsheet__cancel van-hairline--top"
bind:tap="onCancel"
>
{{ cancelText }}
</view>
<view wx:else class="van-actionsheet__content">
<slot />
</view>
</van-popup>