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>
|
import { use } from '../utils';
|
||||||
<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 Touch from '../mixins/touch';
|
import Touch from '../mixins/touch';
|
||||||
|
import ClickOutside from '../mixins/click-outside';
|
||||||
|
|
||||||
|
const [sfc, bem] = use('swipe-cell');
|
||||||
const THRESHOLD = 0.15;
|
const THRESHOLD = 0.15;
|
||||||
|
|
||||||
export default create({
|
export default sfc({
|
||||||
name: 'swipe-cell',
|
mixins: [Touch, ClickOutside({
|
||||||
|
event: 'touchstart',
|
||||||
mixins: [Touch],
|
method: 'onClick'
|
||||||
|
})],
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
onClose: Function,
|
onClose: Function,
|
||||||
@ -51,10 +18,6 @@ export default create({
|
|||||||
rightWidth: Number
|
rightWidth: Number
|
||||||
},
|
},
|
||||||
|
|
||||||
directives: {
|
|
||||||
Clickoutside
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
offset: 0,
|
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: {
|
methods: {
|
||||||
open(position) {
|
open(position) {
|
||||||
const offset = position === 'left' ? this.leftWidth : -this.rightWidth;
|
const offset = position === 'left' ? this.leftWidth : -this.rightWidth;
|
||||||
@ -95,12 +49,12 @@ export default create({
|
|||||||
|
|
||||||
swipeLeaveTransition(direction) {
|
swipeLeaveTransition(direction) {
|
||||||
const { offset, leftWidth, rightWidth } = this;
|
const { offset, leftWidth, rightWidth } = this;
|
||||||
const threshold = this.opened ? (1 - THRESHOLD) : THRESHOLD;
|
const threshold = this.opened ? 1 - THRESHOLD : THRESHOLD;
|
||||||
|
|
||||||
// right
|
// right
|
||||||
if (direction > 0 && -offset > rightWidth * threshold && rightWidth > 0) {
|
if (direction > 0 && -offset > rightWidth * threshold && rightWidth > 0) {
|
||||||
this.open('right');
|
this.open('right');
|
||||||
// left
|
// left
|
||||||
} else if (direction < 0 && offset > leftWidth * threshold && leftWidth > 0) {
|
} else if (direction < 0 && offset > leftWidth * threshold && leftWidth > 0) {
|
||||||
this.open('left');
|
this.open('left');
|
||||||
} else {
|
} else {
|
||||||
@ -129,8 +83,10 @@ export default create({
|
|||||||
this.touchMove(event);
|
this.touchMove(event);
|
||||||
const { deltaX } = this;
|
const { deltaX } = this;
|
||||||
|
|
||||||
if ((deltaX < 0 && (-deltaX > this.rightWidth || !this.rightWidth)) ||
|
if (
|
||||||
(deltaX > 0 && ((deltaX > this.leftWidth || deltaX > 0) && !this.leftWidth))) {
|
(deltaX < 0 && (-deltaX > this.rightWidth || !this.rightWidth)) ||
|
||||||
|
(deltaX > 0 && ((deltaX > this.leftWidth || deltaX > 0) && !this.leftWidth))
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,6 +120,50 @@ export default create({
|
|||||||
this.swipeMove(0);
|
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