CellSwipe: code review

This commit is contained in:
陈嘉涵 2017-08-24 20:36:24 +08:00
parent c7b96bd8e0
commit c5474b2106
2 changed files with 86 additions and 96 deletions

View File

@ -1,15 +1,19 @@
<template> <template>
<div v-clickoutside:touchstart="swipeMove" @click="swipeMove()" @touchstart="startDrag" @touchmove="onDrag" @touchend="endDrag" class="van-cell-swipe" ref="cell"> <div
<div class="van-cell-wrapper"> v-clickoutside:touchstart="swipeMove"
<slot>单元格内容</slot> class="van-cell-swipe"
</div> @click="swipeMove()"
<div class="van-cell-left"> @touchstart="startDrag"
<div ref="left"> @touchmove="onDrag"
@touchend="endDrag"
@touchcancel="endDrag"
>
<div class="van-cell-swipe__wrapper" :style="wrapperStyle" @transitionend="swipe = false">
<div class="van-cell-swipe__left" v-if="leftWidth">
<slot name="left"></slot> <slot name="left"></slot>
</div> </div>
</div> <slot></slot>
<div class="van-cell-right"> <div class="van-cell-swipe__right" v-if="rightWidth">
<div ref="right">
<slot name="right"></slot> <slot name="right"></slot>
</div> </div>
</div> </div>
@ -17,112 +21,101 @@
</template> </template>
<script> <script>
import { once } from '../utils/dom';
import Clickoutside from '../utils/clickoutside'; import Clickoutside from '../utils/clickoutside';
export default { export default {
name: 'van-cell-swipe', name: 'van-cell-swipe',
props: { props: {
'leftWidth': { type: Number, default: 0 }, leftWidth: {
'rightWidth': { type: Number, default: 0 } type: Number,
}, default: 0
directives: { Clickoutside },
data() {
return {
start: { x: 0, y: 0 }
};
},
computed: {
leftDefaultTransform() {
return this.translate3d(-this.leftWidth - 1);
}, },
rightDefaultTransform() { rightWidth: {
return this.translate3d(this.rightWidth); type: Number,
default: 0
} }
}, },
mounted() {
this.wrap = this.$refs.cell.querySelector('.van-cell-wrapper');
this.leftElm = this.$refs.left;
this.leftWrapElm = this.leftElm.parentNode;
this.leftWrapElm.style.webkitTransform = this.leftDefaultTransform;
this.rightElm = this.$refs.right; directives: {
this.rightWrapElm = this.rightElm.parentNode; Clickoutside
this.rightWrapElm.style.webkitTransform = this.rightDefaultTransform;
}, },
data() {
return {
offset: 0
};
},
computed: {
wrapperStyle() {
return {
transform: `translate3d(${this.offset}px, 0, 0)`
}
}
},
methods: { methods: {
resetSwipeStatus() { resetSwipeStatus() {
this.swiping = false; // this.swiping = false; //
this.opened = true; // this.opened = true; //
this.offsetLeft = 0; //
},
translate3d(offset) {
return `translate3d(${offset}px, 0, 0)`;
}, },
swipeMove(offset = 0) { swipeMove(offset = 0) {
this.wrap.style.webkitTransform = this.translate3d(offset); this.offset = offset;
this.rightWrapElm.style.webkitTransform = this.translate3d(this.rightWidth + offset);
this.leftWrapElm.style.webkitTransform = this.translate3d(-this.leftWidth + offset);
offset && (this.swiping = true); offset && (this.swiping = true);
}, },
swipeLeaveTransition(direction) { swipeLeaveTransition(direction) {
setTimeout(() => { const { offset, leftWidth, rightWidth } = this;
this.swipeLeave = true; // right
// left if (direction > 0 && -offset > rightWidth * 0.4 && rightWidth > 0) {
if (direction > 0 && -this.offsetLeft > this.rightWidth * 0.4 && this.rightWidth > 0) { this.swipeMove(-rightWidth);
this.swipeMove(-this.rightWidth); this.resetSwipeStatus();
this.resetSwipeStatus(); }
return; // left
// right else if (direction < 0 && offset >leftWidth * 0.4 && leftWidth > 0) {
} else if (direction < 0 && this.offsetLeft > this.leftWidth * 0.4 && this.leftWidth > 0) { this.swipeMove(leftWidth);
this.swipeMove(this.leftWidth); this.resetSwipeStatus();
this.resetSwipeStatus(); } else {
return; this.swipeMove();
} else { }
this.swipeMove(0);
once(this.wrap, 'webkitTransitionEnd', () => {
this.wrap.style.webkitTransform = '';
this.rightWrapElm.style.webkitTransform = this.rightDefaultTransform;
this.leftWrapElm.style.webkitTransform = this.leftDefaultTransform;
this.swipeLeave = false;
this.swiping = false;
});
}
}, 0);
}, },
startDrag(evt) {
evt = evt.changedTouches ? evt.changedTouches[0] : evt; startDrag(event) {
this.dragging = true; this.startX = event.changedTouches[0].pageX;
this.start.x = evt.pageX; this.startY = event.changedTouches[0].pageY;
this.start.y = evt.pageY;
}, },
onDrag(evt) {
onDrag(event) {
if (this.opened) { if (this.opened) {
!this.swiping && this.swipeMove(0); !this.swiping && this.swipeMove();
this.opened = false; this.opened = false;
return; return;
} }
if (!this.dragging) return;
let swiping; const offsetTop = event.changedTouches[0].pageY - this.startY;
const e = evt.changedTouches ? evt.changedTouches[0] : evt; const offsetLeft = event.changedTouches[0].pageX - this.startX;
const offsetTop = e.pageY - this.start.y;
const offsetLeft = this.offsetLeft = e.pageX - this.start.x;
if ((offsetLeft < 0 && -offsetLeft > this.rightWidth) || if ((offsetLeft < 0 && -offsetLeft > this.rightWidth) ||
(offsetLeft > 0 && offsetLeft > this.leftWidth) || (offsetLeft > 0 && offsetLeft > this.leftWidth) ||
(offsetLeft > 0 && !this.leftWidth) || (offsetLeft > 0 && !this.leftWidth) ||
(offsetLeft < 0 && !this.rightWidth)) { (offsetLeft < 0 && !this.rightWidth)) {
return; return;
} }
const y = Math.abs(offsetTop); const y = Math.abs(offsetTop);
const x = Math.abs(offsetLeft); const x = Math.abs(offsetLeft);
swiping = !(x < 5 || (x >= 5 && y >= x * 1.73)); const swiping = !(x < 5 || (x >= 5 && y >= x * 1.73));
if (!swiping) return; if (swiping) {
evt.preventDefault(); event.preventDefault();
this.swipeMove(offsetLeft); this.swipeMove(offsetLeft);
};
}, },
endDrag() { endDrag() {
if (!this.swiping) return; if (this.swiping) {
this.swipeLeaveTransition(this.offsetLeft > 0 ? -1 : 1); this.swipeLeaveTransition(this.offset > 0 ? -1 : 1);
};
} }
} }
}; };

View File

@ -1,29 +1,26 @@
.van-cell { .van-cell-swipe {
&-swipe { overflow: hidden;
position: relative; position: relative;
min-height: 48px;
overflow: hidden;
.van-cell-wrapper, &__wrapper,
.van-cell-left, &__left,
.van-cell-right { &__right {
transition: transform 150ms ease-in-out; transition: transform .15s ease-in-out;
}
} }
&-left, &__left,
&-right { &__right {
position: absolute;
height: 100%;
top: 0; top: 0;
height: 100%;
position: absolute;
} }
&-left { &__left {
left: 0; left: 0;
transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0);
} }
&-right { &__right {
right: 0; right: 0;
transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0);
} }