[new feature] Stepper: support long press gesture (#3711)

This commit is contained in:
neverland 2019-07-01 19:38:03 +08:00 committed by GitHub
parent e4ce6137bf
commit 3d0c6ae504
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 117 additions and 15 deletions

View File

@ -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>
);

View File

@ -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);
});