mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
[improvement] SwipeCell: jsx (#2632)
This commit is contained in:
parent
874d2f79ca
commit
ccdfc7124a
17
packages/mixins/click-outside.js
Normal file
17
packages/mixins/click-outside.js
Normal file
@ -0,0 +1,17 @@
|
||||
import { on, off } from '../utils/event';
|
||||
|
||||
export default config => ({
|
||||
mounted() {
|
||||
config.handler = event => {
|
||||
if (!this.$el.contains(event.target)) {
|
||||
this[config.method]();
|
||||
}
|
||||
};
|
||||
|
||||
on(document, config.event, config.handler);
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
off(document, config.event, config.handler);
|
||||
}
|
||||
});
|
@ -1,48 +1,15 @@
|
||||
<template>
|
||||
<div
|
||||
v-clickoutside:touchstart="onClick"
|
||||
:class="b()"
|
||||
@click="onClick('cell')"
|
||||
@touchstart="startDrag"
|
||||
@touchmove="onDrag"
|
||||
@touchend="endDrag"
|
||||
@touchcancel="endDrag"
|
||||
>
|
||||
<div
|
||||
:class="b('wrapper')"
|
||||
:style="wrapperStyle"
|
||||
@transitionend="swipe = false"
|
||||
>
|
||||
<div
|
||||
v-if="leftWidth"
|
||||
:class="b('left')"
|
||||
@click.stop="onClick('left')"
|
||||
>
|
||||
<slot name="left" />
|
||||
</div>
|
||||
<slot />
|
||||
<div
|
||||
v-if="rightWidth"
|
||||
:class="b('right')"
|
||||
@click.stop="onClick('right')"
|
||||
>
|
||||
<slot name="right" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import create from '../utils/create';
|
||||
import Clickoutside from '../utils/clickoutside';
|
||||
import { use } from '../utils';
|
||||
import Touch from '../mixins/touch';
|
||||
import ClickOutside from '../mixins/click-outside';
|
||||
|
||||
const [sfc, bem] = use('swipe-cell');
|
||||
const THRESHOLD = 0.15;
|
||||
|
||||
export default create({
|
||||
name: 'swipe-cell',
|
||||
|
||||
mixins: [Touch],
|
||||
export default sfc({
|
||||
mixins: [Touch, ClickOutside({
|
||||
event: 'touchstart',
|
||||
method: 'onClick'
|
||||
})],
|
||||
|
||||
props: {
|
||||
onClose: Function,
|
||||
@ -51,10 +18,6 @@ export default create({
|
||||
rightWidth: Number
|
||||
},
|
||||
|
||||
directives: {
|
||||
Clickoutside
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
offset: 0,
|
||||
@ -62,15 +25,6 @@ export default create({
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
wrapperStyle() {
|
||||
return {
|
||||
transform: `translate3d(${this.offset}px, 0, 0)`,
|
||||
transition: this.draging ? 'none' : '.6s cubic-bezier(0.18, 0.89, 0.32, 1)'
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
open(position) {
|
||||
const offset = position === 'left' ? this.leftWidth : -this.rightWidth;
|
||||
@ -95,7 +49,7 @@ export default create({
|
||||
|
||||
swipeLeaveTransition(direction) {
|
||||
const { offset, leftWidth, rightWidth } = this;
|
||||
const threshold = this.opened ? (1 - THRESHOLD) : THRESHOLD;
|
||||
const threshold = this.opened ? 1 - THRESHOLD : THRESHOLD;
|
||||
|
||||
// right
|
||||
if (direction > 0 && -offset > rightWidth * threshold && rightWidth > 0) {
|
||||
@ -129,8 +83,10 @@ export default create({
|
||||
this.touchMove(event);
|
||||
const { deltaX } = this;
|
||||
|
||||
if ((deltaX < 0 && (-deltaX > this.rightWidth || !this.rightWidth)) ||
|
||||
(deltaX > 0 && ((deltaX > this.leftWidth || deltaX > 0) && !this.leftWidth))) {
|
||||
if (
|
||||
(deltaX < 0 && (-deltaX > this.rightWidth || !this.rightWidth)) ||
|
||||
(deltaX > 0 && ((deltaX > this.leftWidth || deltaX > 0) && !this.leftWidth))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -164,6 +120,50 @@ export default create({
|
||||
this.swipeMove(0);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
render(h) {
|
||||
const onClick = (position, stop) => event => {
|
||||
if (stop) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
this.onClick(position);
|
||||
};
|
||||
|
||||
const wrapperStyle = {
|
||||
transform: `translate3d(${this.offset}px, 0, 0)`,
|
||||
transition: this.draging ? 'none' : '.6s cubic-bezier(0.18, 0.89, 0.32, 1)'
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
class={bem()}
|
||||
onClick={onClick('cell')}
|
||||
onTouchstart={this.startDrag}
|
||||
onTouchmove={this.onDrag}
|
||||
onTouchend={this.endDrag}
|
||||
onTouchcancel={this.endDrag}
|
||||
>
|
||||
<div
|
||||
class={bem('wrapper')}
|
||||
style={wrapperStyle}
|
||||
onTransitionend={() => {
|
||||
this.swipe = false;
|
||||
}}
|
||||
>
|
||||
{this.leftWidth && (
|
||||
<div class={bem('left')} onClick={onClick('left', true)}>
|
||||
{this.$slots.left}
|
||||
</div>
|
||||
)}
|
||||
{this.$slots.default}
|
||||
{this.rightWidth && (
|
||||
<div class={bem('right')} onClick={onClick('right', true)}>
|
||||
{this.$slots.right}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
</script>
|
@ -1,44 +0,0 @@
|
||||
/**
|
||||
* v-clickoutside
|
||||
*
|
||||
* ```vue
|
||||
* <div v-clickoutside="onClose">
|
||||
* ```
|
||||
*/
|
||||
|
||||
import { on, off } from './event';
|
||||
|
||||
const context = '@@clickoutsideContext';
|
||||
|
||||
export default {
|
||||
bind(el, binding) {
|
||||
const handler = event => {
|
||||
if (!el.contains(event.target)) {
|
||||
el[context].callback();
|
||||
}
|
||||
};
|
||||
|
||||
el[context] = {
|
||||
handler,
|
||||
callback: binding.value,
|
||||
arg: binding.arg || 'click'
|
||||
};
|
||||
|
||||
on(document, el[context].arg, handler);
|
||||
},
|
||||
|
||||
update(el, binding) {
|
||||
el[context].callback = binding.value;
|
||||
},
|
||||
|
||||
unbind(el) {
|
||||
off(document, el[context].arg, el[context].handler);
|
||||
},
|
||||
|
||||
install(Vue) {
|
||||
Vue.directive('clickoutside', {
|
||||
bind: this.bind,
|
||||
unbind: this.unbind
|
||||
});
|
||||
}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user