From 40ce5cf61ad71ed09e9771d402e20e378984afe7 Mon Sep 17 00:00:00 2001 From: rex Date: Tue, 30 Oct 2018 10:20:23 +0800 Subject: [PATCH] [new feature] SwipeCell: add new component swipe-cell --- example/app.json | 3 +- example/config.js | 4 + example/pages/swipe-cell/index.js | 21 +++++ example/pages/swipe-cell/index.json | 10 ++ example/pages/swipe-cell/index.wxml | 21 +++++ example/pages/swipe-cell/index.wxss | 15 +++ packages/swipe-cell/README.md | 98 ++++++++++++++++++++ packages/swipe-cell/index.json | 3 + packages/swipe-cell/index.less | 23 +++++ packages/swipe-cell/index.ts | 139 ++++++++++++++++++++++++++++ packages/swipe-cell/index.wxml | 22 +++++ 11 files changed, 358 insertions(+), 1 deletion(-) create mode 100644 example/pages/swipe-cell/index.js create mode 100644 example/pages/swipe-cell/index.json create mode 100644 example/pages/swipe-cell/index.wxml create mode 100644 example/pages/swipe-cell/index.wxss create mode 100644 packages/swipe-cell/README.md create mode 100644 packages/swipe-cell/index.json create mode 100644 packages/swipe-cell/index.less create mode 100644 packages/swipe-cell/index.ts create mode 100644 packages/swipe-cell/index.wxml diff --git a/example/app.json b/example/app.json index ce963064..b74be0dc 100644 --- a/example/app.json +++ b/example/app.json @@ -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", diff --git a/example/config.js b/example/config.js index b390f9a1..d4c950d3 100644 --- a/example/config.js +++ b/example/config.js @@ -125,6 +125,10 @@ export default [ { groupName: '高阶组件', list: [ + { + path: '/swipe-cell', + title: 'SwipeCell 滑动单元格' + }, { path: '/switch-cell', title: 'SwitchCell 开关单元格' diff --git a/example/pages/swipe-cell/index.js b/example/pages/swipe-cell/index.js new file mode 100644 index 00000000..d6add432 --- /dev/null +++ b/example/pages/swipe-cell/index.js @@ -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; + } + } +}); diff --git a/example/pages/swipe-cell/index.json b/example/pages/swipe-cell/index.json new file mode 100644 index 00000000..adf08de0 --- /dev/null +++ b/example/pages/swipe-cell/index.json @@ -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" + } +} diff --git a/example/pages/swipe-cell/index.wxml b/example/pages/swipe-cell/index.wxml new file mode 100644 index 00000000..30aece28 --- /dev/null +++ b/example/pages/swipe-cell/index.wxml @@ -0,0 +1,21 @@ + + + 选择 + + + + 删除 + + + + + + 选择 + + + + 删除 + + + + diff --git a/example/pages/swipe-cell/index.wxss b/example/pages/swipe-cell/index.wxss new file mode 100644 index 00000000..b14c9cfb --- /dev/null +++ b/example/pages/swipe-cell/index.wxss @@ -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; +} diff --git a/packages/swipe-cell/README.md b/packages/swipe-cell/README.md new file mode 100644 index 00000000..0dc9da9c --- /dev/null +++ b/packages/swipe-cell/README.md @@ -0,0 +1,98 @@ +## SwipeCell 滑动单元格 + +### 使用指南 +在 index.json 中引入组件 +```json +"usingComponents": { + "van-swipe-cell": "path/to/vant-weapp/dist/swipe-cell/index" +} +``` + +### 代码演示 + +#### 基础用法 + +```html + + 选择 + + + + 删除 + +``` + +#### 异步关闭 + +```html + + 选择 + + + + 删除 + +``` + +```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 | - | - | 收起单元格侧边栏 | diff --git a/packages/swipe-cell/index.json b/packages/swipe-cell/index.json new file mode 100644 index 00000000..467ce294 --- /dev/null +++ b/packages/swipe-cell/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/packages/swipe-cell/index.less b/packages/swipe-cell/index.less new file mode 100644 index 00000000..a3ff8731 --- /dev/null +++ b/packages/swipe-cell/index.less @@ -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); + } +} diff --git a/packages/swipe-cell/index.ts b/packages/swipe-cell/index.ts new file mode 100644 index 00000000..3a39a7aa --- /dev/null +++ b/packages/swipe-cell/index.ts @@ -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); + } + } + } +}); diff --git a/packages/swipe-cell/index.wxml b/packages/swipe-cell/index.wxml new file mode 100644 index 00000000..45f05097 --- /dev/null +++ b/packages/swipe-cell/index.wxml @@ -0,0 +1,22 @@ + + + + + + + + + + +