[new feature] SwipeCell: add new component swipe-cell

This commit is contained in:
rex 2018-10-30 10:20:23 +08:00 committed by GitHub
parent af500d9bd4
commit 40ce5cf61a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 358 additions and 1 deletions

View File

@ -33,7 +33,8 @@
"pages/submit-bar/index",
"pages/radio/index",
"pages/checkbox/index",
"pages/goods-action/index"
"pages/goods-action/index",
"pages/swipe-cell/index"
],
"window": {
"navigationBarBackgroundColor": "#f8f8f8",

View File

@ -125,6 +125,10 @@ export default [
{
groupName: '高阶组件',
list: [
{
path: '/swipe-cell',
title: 'SwipeCell 滑动单元格'
},
{
path: '/switch-cell',
title: 'SwitchCell 开关单元格'

View File

@ -0,0 +1,21 @@
import Page from '../../common/page';
import Dialog from '../../dist/dialog/dialog';
Page({
onClose(event) {
const { position, instance } = event.detail;
switch (position) {
case 'left':
case 'cell':
instance.close();
break;
case 'right':
Dialog.confirm({
message: '确定删除吗?'
}).then(() => {
instance.close();
});
break;
}
}
});

View File

@ -0,0 +1,10 @@
{
"navigationBarTitleText": "SwipeCell 滑动单元格",
"usingComponents": {
"demo-block": "../../components/demo-block/index",
"van-swipe-cell": "../../dist/swipe-cell/index",
"van-cell-group": "../../dist/cell-group/index",
"van-cell": "../../dist/cell/index",
"van-dialog": "../../dist/dialog/index"
}
}

View File

@ -0,0 +1,21 @@
<demo-block title="基础用法">
<van-swipe-cell right-width="{{ 65 }}" left-width="{{ 65 }}">
<view slot="left" class="van-swipe-cell__left">选择</view>
<van-cell-group>
<van-cell title="单元格" value="内容" />
</van-cell-group>
<view slot="right" class="van-swipe-cell__right">删除</view>
</van-swipe-cell>
</demo-block>
<demo-block title="异步关闭">
<van-swipe-cell id="swipe-cell" right-width="{{ 65 }}" left-width="{{ 65 }}" async-close bind:close="onClose">
<view slot="left" class="van-swipe-cell__left">选择</view>
<van-cell-group>
<van-cell title="单元格" value="内容" />
</van-cell-group>
<view slot="right" class="van-swipe-cell__right">删除</view>
</van-swipe-cell>
</demo-block>
<van-dialog id="van-dialog" />

View File

@ -0,0 +1,15 @@
.demo-swipe-cell {
user-select: none;
}
.van-swipe-cell__left,
.van-swipe-cell__right {
display: inline-block;
width: 65px;
height: 44px;
font-size: 15px;
line-height: 44px;
color: #fff;
text-align: center;
background-color: #f44;
}

View File

@ -0,0 +1,98 @@
## SwipeCell 滑动单元格
### 使用指南
在 index.json 中引入组件
```json
"usingComponents": {
"van-swipe-cell": "path/to/vant-weapp/dist/swipe-cell/index"
}
```
### 代码演示
#### 基础用法
```html
<van-swipe-cell right-width="{{ 65 }}" left-width="{{ 65 }}">
<view slot="left">选择</view>
<van-cell-group>
<van-cell title="单元格" value="内容" />
</van-cell-group>
<view slot="right">删除</view>
</van-swipe-cell>
```
#### 异步关闭
```html
<van-swipe-cell id="swipe-cell" right-width="{{ 65 }}" left-width="{{ 65 }}" async-close bind:close="onClose">
<view slot="left">选择</view>
<van-cell-group>
<van-cell title="单元格" value="内容" />
</van-cell-group>
<view slot="right">删除</view>
</van-swipe-cell>
```
```js
export default {
methods: {
onClose(event) {
const { position, instance } = event.detail;
switch (position) {
case 'left':
case 'cell':
instance.close();
break;
case 'right':
Dialog.confirm({
message: '确定删除吗?'
}).then(() => {
instance.close();
});
break;
}
}
}
}
```
### API
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|------|------|------|------|------|
| left-width | 左侧滑动区域宽度 | `Number` | `0` | - |
| right-width | 右侧滑动区域宽度 | `Number` | `0` | - |
| async-close | 是否异步关闭 | `Boolean` | `false` | - |
| disabled | 是否禁用滑动 | `Boolean` | `false` | 1.3.4 |
### Slot
| 名称 | 说明 |
|------|------|
| - | 自定义显示内容 |
| left | 左侧滑动内容 |
| right | 右侧滑动内容 |
### Event
| 事件名 | 说明 | 参数 |
|------|------|------|
| click | 点击时触发 | 关闭时的点击位置 (`left` `right` `cell` `outside`) |
| close | 点击时触发 | 整体是一个 Object包含 `position`, `instance` 两个 key。 |
### close 参数
| 参数 | 类型 | 说明 |
|------|------|------|
| position | `String` | 关闭时的点击位置 (`left` `right` `cell` `outside`) |
| instance | `Object` | SwipeCell 实例 |
### 方法
通过 selectComponent 可以获取到 SwipeCell 实例并调用实例方法
| 方法名 | 参数 | 返回值 | 介绍 |
|------|------|------|------|
| open | position: `left | right` | - | 打开单元格侧边栏 |
| close | - | - | 收起单元格侧边栏 |

View File

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

View File

@ -0,0 +1,23 @@
@import '../common/style/var.less';
.van-swipe-cell {
position: relative;
overflow: hidden;
&__left,
&__right {
position: absolute;
top: 0;
height: 100%;
}
&__left {
left: 0;
transform: translate3d(-100%, 0, 0);
}
&__right {
right: 0;
transform: translate3d(100%, 0, 0);
}
}

View File

@ -0,0 +1,139 @@
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
const THRESHOLD = 0.15;
VantComponent({
props: {
disabled: Boolean,
leftWidth: {
type: Number,
value: 0
},
rightWidth: {
type: Number,
value: 0
},
asyncClose: Boolean
},
mixins: [touch],
data: {
offset: 0,
draging: false
},
computed: {
wrapperStyle() {
const { offset, draging } = this.data;
return `
transform: translate3d(${offset}px, 0, 0);
transition: ${draging ? 'none' : '.6s cubic-bezier(0.18, 0.89, 0.32, 1)'};
`;
}
},
methods: {
onTransitionend() {
this.swipe = false;
},
open(position) {
const { leftWidth, rightWidth } = this.data;
const offset = position === 'left' ? leftWidth : -rightWidth;
this.swipeMove(offset);
this.resetSwipeStatus();
},
close() {
this.setData({ offset: 0 });
},
resetSwipeStatus() {
this.swiping = false;
this.opened = true;
},
swipeMove(offset = 0) {
this.setData({ offset });
offset && (this.swiping = true);
!offset && (this.opened = false);
},
swipeLeaveTransition(direction) {
const { offset, leftWidth, rightWidth } = this.data;
const threshold = this.opened ? 1 - THRESHOLD : THRESHOLD;
// right
if (direction > 0 && -offset > rightWidth * threshold && rightWidth > 0) {
this.open('right');
// left
} else if (direction < 0 && offset > leftWidth * threshold && leftWidth > 0) {
this.open('left');
} else {
this.swipeMove();
}
},
startDrag(event) {
if (this.data.disabled) {
return;
}
this.setData({ draging: true });
this.touchStart(event);
if (this.opened) {
this.startX -= this.data.offset;
}
},
onDrag(event) {
if (this.data.disabled) {
return;
}
this.touchMove(event);
const { deltaX } = this;
const { leftWidth, rightWidth } = this.data;
if (
(deltaX < 0 && (-deltaX > rightWidth || !rightWidth)) ||
(deltaX > 0 && (deltaX > leftWidth || (deltaX > 0 && !leftWidth)))
) {
return;
}
if (this.direction === 'horizontal') {
this.swipeMove(deltaX);
}
},
endDrag() {
if (this.data.disabled) {
return;
}
this.setData({ draging: false });
if (this.swiping) {
this.swipeLeaveTransition(this.data.offset > 0 ? -1 : 1);
}
},
onClick(event) {
const { key: position = 'outside' } = event.currentTarget.dataset;
this.$emit('click', position);
if (!this.data.offset) {
return;
}
if (this.data.asyncClose) {
this.$emit('close', { position, instance: this });
} else {
this.swipeMove(0);
}
}
}
});

View File

@ -0,0 +1,22 @@
<view
class="van-swipe-cell"
data-key="cell"
bindtap="onClick"
bindtouchstart="startDrag"
bindtouchmove="onDrag"
bindtouchend="endDrag"
bindtouchcancel="endDrag"
>
<view
style="{{ wrapperStyle }}"
bindtransitionend="onTransitionend"
>
<view wx:if="{{ leftWidth }}" class="van-swipe-cell__left" data-key="left" catch:tap="onClick">
<slot name="left" />
</view>
<slot />
<view wx:if="{{ rightWidth }}" class="van-swipe-cell__right" data-key="right" catch:tap="onClick">
<slot name="right" />
</view>
</view>
</view>