mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
[new feature] Stepper: support long press gesture (#3711)
This commit is contained in:
parent
e4ce6137bf
commit
3d0c6ae504
@ -2,6 +2,9 @@ import { createNamespace, isDef, suffixPx } from '../utils';
|
||||
|
||||
const [createComponent, bem] = createNamespace('stepper');
|
||||
|
||||
const LONG_PRESS_START_TIME = 600;
|
||||
const LONG_PRESS_INTERVAL = 200;
|
||||
|
||||
export default createComponent({
|
||||
props: {
|
||||
value: null,
|
||||
@ -78,19 +81,21 @@ export default createComponent({
|
||||
const { value } = event.target;
|
||||
const formatted = this.format(value);
|
||||
|
||||
if (!this.asyncChange) {
|
||||
if (this.asyncChange) {
|
||||
event.target.value = this.currentValue;
|
||||
this.$emit('input', formatted);
|
||||
this.$emit('change', formatted);
|
||||
} else {
|
||||
if (+value !== formatted) {
|
||||
event.target.value = formatted;
|
||||
}
|
||||
this.currentValue = formatted;
|
||||
} else {
|
||||
event.target.value = this.currentValue;
|
||||
this.$emit('input', formatted);
|
||||
this.$emit('change', formatted);
|
||||
}
|
||||
},
|
||||
|
||||
onChange(type) {
|
||||
onChange() {
|
||||
const { type } = this;
|
||||
|
||||
if (this[`${type}Disabled`]) {
|
||||
this.$emit('overlimit', type);
|
||||
return;
|
||||
@ -99,12 +104,13 @@ export default createComponent({
|
||||
const diff = type === 'minus' ? -this.step : +this.step;
|
||||
const value = Math.round((this.currentValue + diff) * 100) / 100;
|
||||
|
||||
if (!this.asyncChange) {
|
||||
this.currentValue = this.range(value);
|
||||
} else {
|
||||
if (this.asyncChange) {
|
||||
this.$emit('input', value);
|
||||
this.$emit('change', value);
|
||||
} else {
|
||||
this.currentValue = this.range(value);
|
||||
}
|
||||
|
||||
this.$emit(type);
|
||||
},
|
||||
|
||||
@ -120,19 +126,56 @@ export default createComponent({
|
||||
if (this.currentValue === 0) {
|
||||
event.target.value = this.currentValue;
|
||||
}
|
||||
},
|
||||
|
||||
longPressStep() {
|
||||
this.longPressTimer = setTimeout(() => {
|
||||
this.onChange(this.type);
|
||||
this.longPressStep(this.type);
|
||||
}, LONG_PRESS_INTERVAL);
|
||||
},
|
||||
|
||||
onTouchStart(type) {
|
||||
clearTimeout(this.longPressTimer);
|
||||
this.isLongPress = false;
|
||||
|
||||
this.longPressTimer = setTimeout(() => {
|
||||
this.isLongPress = true;
|
||||
this.onChange();
|
||||
this.longPressStep();
|
||||
}, LONG_PRESS_START_TIME);
|
||||
},
|
||||
|
||||
onTouchEnd(event) {
|
||||
clearTimeout(this.longPressTimer);
|
||||
|
||||
if (this.isLongPress) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
render(h) {
|
||||
const onChange = type => () => {
|
||||
this.onChange(type);
|
||||
};
|
||||
const createListeners = type => ({
|
||||
on: {
|
||||
click: () => {
|
||||
this.type = type;
|
||||
this.onChange();
|
||||
},
|
||||
touchstart: () => {
|
||||
this.type = type;
|
||||
this.onTouchStart(type);
|
||||
},
|
||||
touchend: this.onTouchEnd,
|
||||
touchcancel: this.onTouchEnd
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div class={bem()}>
|
||||
<button
|
||||
class={bem('minus', { disabled: this.minusDisabled })}
|
||||
onClick={onChange('minus')}
|
||||
{...createListeners('minus')}
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
@ -150,7 +193,7 @@ export default createComponent({
|
||||
/>
|
||||
<button
|
||||
class={bem('plus', { disabled: this.plusDisabled })}
|
||||
onClick={onChange('plus')}
|
||||
{...createListeners('plus')}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Stepper from '..';
|
||||
import { mount } from '../../../test/utils';
|
||||
import { mount, later } from '../../../test/utils';
|
||||
|
||||
test('disabled stepper', () => {
|
||||
const wrapper = mount(Stepper, {
|
||||
@ -39,6 +39,27 @@ test('click button', () => {
|
||||
expect(wrapper.emitted('overlimit')).toEqual([['plus'], ['minus']]);
|
||||
});
|
||||
|
||||
test('long press', async () => {
|
||||
const wrapper = mount(Stepper, {
|
||||
propsData: {
|
||||
value: 1
|
||||
}
|
||||
});
|
||||
|
||||
const plus = wrapper.find('.van-stepper__plus');
|
||||
|
||||
plus.trigger('touchstart');
|
||||
plus.trigger('touchend');
|
||||
plus.trigger('click');
|
||||
|
||||
expect(wrapper.emitted('input')[0][0]).toEqual(2);
|
||||
|
||||
plus.trigger('touchstart');
|
||||
await later(1000);
|
||||
plus.trigger('touchend');
|
||||
expect(wrapper.emitted('input')).toEqual([[2], [3], [4]]);
|
||||
});
|
||||
|
||||
test('correct value when value is not correct', () => {
|
||||
const wrapper = mount(Stepper, {
|
||||
propsData: {
|
||||
@ -117,3 +138,41 @@ test('input width', () => {
|
||||
});
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('async change', () => {
|
||||
const wrapper = mount(Stepper, {
|
||||
propsData: {
|
||||
value: 1,
|
||||
asyncChange: true
|
||||
}
|
||||
});
|
||||
|
||||
const plus = wrapper.find('.van-stepper__plus');
|
||||
plus.trigger('click');
|
||||
|
||||
expect(wrapper.emitted('input')[0][0]).toEqual(2);
|
||||
expect(wrapper.emitted('change')[0][0]).toEqual(2);
|
||||
|
||||
const input = wrapper.find('input');
|
||||
input.element.value = '3';
|
||||
input.trigger('input');
|
||||
|
||||
expect(wrapper.emitted('input')[1][0]).toEqual(3);
|
||||
expect(wrapper.emitted('change')[1][0]).toEqual(3);
|
||||
});
|
||||
|
||||
test('min value is 0', () => {
|
||||
const wrapper = mount(Stepper, {
|
||||
propsData: {
|
||||
value: 1,
|
||||
min: 0
|
||||
}
|
||||
});
|
||||
|
||||
const input = wrapper.find('input');
|
||||
input.element.value = '';
|
||||
input.trigger('input');
|
||||
input.trigger('blur');
|
||||
|
||||
expect(wrapper.emitted('input')[0][0]).toEqual(0);
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user