mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-24 02:16:12 +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 [createComponent, bem] = createNamespace('stepper');
|
||||||
|
|
||||||
|
const LONG_PRESS_START_TIME = 600;
|
||||||
|
const LONG_PRESS_INTERVAL = 200;
|
||||||
|
|
||||||
export default createComponent({
|
export default createComponent({
|
||||||
props: {
|
props: {
|
||||||
value: null,
|
value: null,
|
||||||
@ -78,19 +81,21 @@ export default createComponent({
|
|||||||
const { value } = event.target;
|
const { value } = event.target;
|
||||||
const formatted = this.format(value);
|
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) {
|
if (+value !== formatted) {
|
||||||
event.target.value = formatted;
|
event.target.value = formatted;
|
||||||
}
|
}
|
||||||
this.currentValue = 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`]) {
|
if (this[`${type}Disabled`]) {
|
||||||
this.$emit('overlimit', type);
|
this.$emit('overlimit', type);
|
||||||
return;
|
return;
|
||||||
@ -99,12 +104,13 @@ export default createComponent({
|
|||||||
const diff = type === 'minus' ? -this.step : +this.step;
|
const diff = type === 'minus' ? -this.step : +this.step;
|
||||||
const value = Math.round((this.currentValue + diff) * 100) / 100;
|
const value = Math.round((this.currentValue + diff) * 100) / 100;
|
||||||
|
|
||||||
if (!this.asyncChange) {
|
if (this.asyncChange) {
|
||||||
this.currentValue = this.range(value);
|
|
||||||
} else {
|
|
||||||
this.$emit('input', value);
|
this.$emit('input', value);
|
||||||
this.$emit('change', value);
|
this.$emit('change', value);
|
||||||
|
} else {
|
||||||
|
this.currentValue = this.range(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$emit(type);
|
this.$emit(type);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -120,19 +126,56 @@ export default createComponent({
|
|||||||
if (this.currentValue === 0) {
|
if (this.currentValue === 0) {
|
||||||
event.target.value = this.currentValue;
|
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) {
|
render(h) {
|
||||||
const onChange = type => () => {
|
const createListeners = type => ({
|
||||||
this.onChange(type);
|
on: {
|
||||||
};
|
click: () => {
|
||||||
|
this.type = type;
|
||||||
|
this.onChange();
|
||||||
|
},
|
||||||
|
touchstart: () => {
|
||||||
|
this.type = type;
|
||||||
|
this.onTouchStart(type);
|
||||||
|
},
|
||||||
|
touchend: this.onTouchEnd,
|
||||||
|
touchcancel: this.onTouchEnd
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={bem()}>
|
<div class={bem()}>
|
||||||
<button
|
<button
|
||||||
class={bem('minus', { disabled: this.minusDisabled })}
|
class={bem('minus', { disabled: this.minusDisabled })}
|
||||||
onClick={onChange('minus')}
|
{...createListeners('minus')}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
@ -150,7 +193,7 @@ export default createComponent({
|
|||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
class={bem('plus', { disabled: this.plusDisabled })}
|
class={bem('plus', { disabled: this.plusDisabled })}
|
||||||
onClick={onChange('plus')}
|
{...createListeners('plus')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Stepper from '..';
|
import Stepper from '..';
|
||||||
import { mount } from '../../../test/utils';
|
import { mount, later } from '../../../test/utils';
|
||||||
|
|
||||||
test('disabled stepper', () => {
|
test('disabled stepper', () => {
|
||||||
const wrapper = mount(Stepper, {
|
const wrapper = mount(Stepper, {
|
||||||
@ -39,6 +39,27 @@ test('click button', () => {
|
|||||||
expect(wrapper.emitted('overlimit')).toEqual([['plus'], ['minus']]);
|
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', () => {
|
test('correct value when value is not correct', () => {
|
||||||
const wrapper = mount(Stepper, {
|
const wrapper = mount(Stepper, {
|
||||||
propsData: {
|
propsData: {
|
||||||
@ -117,3 +138,41 @@ test('input width', () => {
|
|||||||
});
|
});
|
||||||
expect(wrapper).toMatchSnapshot();
|
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