From 3d0c6ae5040aeeec7b3703716aa834e9e22408ee Mon Sep 17 00:00:00 2001 From: neverland Date: Mon, 1 Jul 2019 19:38:03 +0800 Subject: [PATCH] [new feature] Stepper: support long press gesture (#3711) --- src/stepper/index.js | 71 +++++++++++++++++++++++++++------- src/stepper/test/index.spec.js | 61 ++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 15 deletions(-) diff --git a/src/stepper/index.js b/src/stepper/index.js index f354cadd9..2aafe0ad8 100644 --- a/src/stepper/index.js +++ b/src/stepper/index.js @@ -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 (
); diff --git a/src/stepper/test/index.spec.js b/src/stepper/test/index.spec.js index 3bbbff824..d5ff00f2b 100644 --- a/src/stepper/test/index.spec.js +++ b/src/stepper/test/index.spec.js @@ -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); +});