Skip to content

Commit f3b9504

Browse files
committed
fix(checkbox, radio, slider, switch): fixed onChange event emit timing
1 parent accf20d commit f3b9504

8 files changed

Lines changed: 182 additions & 9 deletions

File tree

packages/varlet-ui/src/checkbox-group/__tests__/index.spec.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,29 @@ test('checkbox onClick & onChange', async () => {
7777
wrapper.unmount()
7878
})
7979

80+
test('checkbox emits update before change', async () => {
81+
const calls = []
82+
const onUpdateModelValue = vi.fn((value) => {
83+
calls.push('update')
84+
wrapper.setProps({ modelValue: value })
85+
})
86+
const onChange = vi.fn(() => calls.push('change'))
87+
88+
const wrapper = mount(VarCheckbox, {
89+
props: {
90+
modelValue: false,
91+
onChange,
92+
'onUpdate:modelValue': onUpdateModelValue,
93+
},
94+
})
95+
96+
await wrapper.find('.var-checkbox').trigger('click')
97+
98+
expect(calls).toStrictEqual(['update', 'change'])
99+
100+
wrapper.unmount()
101+
})
102+
80103
test('checkbox toggle method', async () => {
81104
const onUpdateModelValue = vi.fn((value) => wrapper.setProps({ modelValue: value }))
82105

@@ -188,6 +211,39 @@ test('checkbox with checkbox group', async () => {
188211
wrapper.unmount()
189212
})
190213

214+
test('checkbox group emits update before child change', async () => {
215+
const wrapper = mount({
216+
components: {
217+
[VarCheckboxGroup.name]: VarCheckboxGroup,
218+
[VarCheckbox.name]: VarCheckbox,
219+
},
220+
data: () => ({
221+
value: [],
222+
calls: [],
223+
}),
224+
methods: {
225+
handleUpdate(value) {
226+
this.value = value
227+
this.calls.push('update')
228+
},
229+
handleChange() {
230+
this.calls.push('change')
231+
},
232+
},
233+
template: `
234+
<var-checkbox-group :model-value="value" @update:model-value="handleUpdate">
235+
<var-checkbox :checked-value="1" @change="handleChange" />
236+
</var-checkbox-group>
237+
`,
238+
})
239+
240+
await wrapper.find('.var-checkbox').trigger('click')
241+
242+
expect(wrapper.vm.calls).toStrictEqual(['update', 'change'])
243+
244+
wrapper.unmount()
245+
})
246+
191247
test('checkbox validation', async () => {
192248
const onUpdateModelValue = vi.fn((value) => wrapper.setProps({ modelValue: value }))
193249

packages/varlet-ui/src/checkbox/Checkbox.vue

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,16 +123,17 @@ export default defineComponent({
123123
})
124124
}
125125
126-
function change(changedValue: any) {
126+
async function change(changedValue: any) {
127127
const { checkedValue, onChange } = props
128128
129129
value.value = changedValue
130-
call(onChange, value.value, isIndeterminate.value)
131-
validateWithTrigger('onChange')
132130
changedValue === checkedValue ? checkboxGroup?.onChecked(checkedValue) : checkboxGroup?.onUnchecked(checkedValue)
131+
await nextTick()
132+
call(onChange, changedValue, isIndeterminate.value)
133+
validateWithTrigger('onChange')
133134
}
134135
135-
function handleClick(e: Event) {
136+
async function handleClick(e: Event) {
136137
const { disabled, readonly, checkedValue, uncheckedValue, onClick } = props
137138
138139
if (form?.disabled.value || disabled) {
@@ -147,6 +148,7 @@ export default defineComponent({
147148
148149
if (isIndeterminate.value === true) {
149150
isIndeterminate.value = false
151+
await nextTick()
150152
call(props.onChange, value.value, isIndeterminate.value)
151153
validateWithTrigger('onChange')
152154
return

packages/varlet-ui/src/radio-group/__tests__/index.spec.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,29 @@ test('radio onClick & onChange', async () => {
7777
wrapper.unmount()
7878
})
7979

80+
test('radio emits update before change', async () => {
81+
const calls = []
82+
const onUpdateModelValue = vi.fn((value) => {
83+
calls.push('update')
84+
wrapper.setProps({ modelValue: value })
85+
})
86+
const onChange = vi.fn(() => calls.push('change'))
87+
88+
const wrapper = mount(VarRadio, {
89+
props: {
90+
modelValue: false,
91+
onChange,
92+
'onUpdate:modelValue': onUpdateModelValue,
93+
},
94+
})
95+
96+
await wrapper.find('.var-radio').trigger('click')
97+
98+
expect(calls).toStrictEqual(['update', 'change'])
99+
100+
wrapper.unmount()
101+
})
102+
80103
test('radio toggle method', async () => {
81104
const onUpdateModelValue = vi.fn((value) => wrapper.setProps({ modelValue: value }))
82105

@@ -172,6 +195,40 @@ test('radio with radio group', async () => {
172195
wrapper.unmount()
173196
})
174197

198+
test('radio group emits update before child change', async () => {
199+
const wrapper = mount({
200+
components: {
201+
[VarRadioGroup.name]: VarRadioGroup,
202+
[VarRadio.name]: VarRadio,
203+
},
204+
data: () => ({
205+
value: 2,
206+
calls: [],
207+
}),
208+
methods: {
209+
handleUpdate(value) {
210+
this.value = value
211+
this.calls.push('update')
212+
},
213+
handleChange() {
214+
this.calls.push('change')
215+
},
216+
},
217+
template: `
218+
<var-radio-group :model-value="value" @update:model-value="handleUpdate">
219+
<var-radio :checked-value="1" @change="handleChange" />
220+
<var-radio :checked-value="2" />
221+
</var-radio-group>
222+
`,
223+
})
224+
225+
await wrapper.find('.var-radio').trigger('click')
226+
227+
expect(wrapper.vm.calls).toStrictEqual(['update', 'change'])
228+
229+
wrapper.unmount()
230+
})
231+
175232
test('radio validation', async () => {
176233
const onUpdateModelValue = vi.fn((value) => wrapper.setProps({ modelValue: value }))
177234

packages/varlet-ui/src/radio/Radio.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,17 +174,17 @@ export default defineComponent({
174174
})
175175
}
176176
177-
function change(changedValue: any) {
177+
async function change(changedValue: any) {
178178
const { checkedValue, onChange } = props
179179
180180
if (radioGroup && value.value === checkedValue) {
181181
return
182182
}
183183
184184
value.value = changedValue
185-
186-
call(onChange, value.value)
187185
radioGroup?.onToggle(checkedValue)
186+
await nextTick()
187+
call(onChange, changedValue)
188188
validateWithTrigger('onChange')
189189
}
190190

packages/varlet-ui/src/slider/Slider.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,8 @@ export default defineComponent({
313313
}
314314
315315
function emitChange(value: number | number[]) {
316-
call(props.onChange, value)
317316
call(props['onUpdate:modelValue'], value)
317+
call(props.onChange, value)
318318
validateWithTrigger()
319319
}
320320

packages/varlet-ui/src/slider/__tests__/index.spec.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,32 @@ describe('test slider props', () => {
211211
wrapper.unmount()
212212
})
213213

214+
test('slider emits update before change', async () => {
215+
const calls = []
216+
const onUpdateModelValue = vi.fn((value) => {
217+
calls.push('update')
218+
wrapper.setProps({ modelValue: value })
219+
})
220+
const onChange = vi.fn(() => calls.push('change'))
221+
222+
const wrapper = mount(VarSlider, {
223+
props: {
224+
modelValue: 0,
225+
onChange,
226+
'onUpdate:modelValue': onUpdateModelValue,
227+
},
228+
})
229+
230+
const el = wrapper.find('.var-slider__horizontal-thumb')
231+
await trigger(el, 'touchstart', 0, 0)
232+
await trigger(document, 'touchmove', 50, 0)
233+
await trigger(document, 'touchend', 50, 0)
234+
235+
expect(calls).toStrictEqual(['update', 'change'])
236+
237+
wrapper.unmount()
238+
})
239+
214240
test('thumbSize prop', () => {
215241
const wrapper = mount(VarSlider, {
216242
props: {

packages/varlet-ui/src/switch/Switch.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,8 @@ export default defineComponent({
213213
validateWithTrigger('onLazyChange')
214214
})
215215
} else {
216-
call(onChange, newValue)
217216
call(updateModelValue, newValue)
217+
call(onChange, newValue)
218218
validateWithTrigger('onChange')
219219
}
220220
}

packages/varlet-ui/src/switch/__tests__/index.spec.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,38 @@ describe('test switch events', () => {
164164
wrapper.unmount()
165165
})
166166

167+
test('switch emits update before change', async () => {
168+
const calls = []
169+
170+
const wrapper = mount({
171+
components: {
172+
[VarSwitch.name]: VarSwitch,
173+
},
174+
data() {
175+
return {
176+
value: true,
177+
calls,
178+
}
179+
},
180+
methods: {
181+
handleUpdate(value) {
182+
this.value = value
183+
this.calls.push('update')
184+
},
185+
handleChange() {
186+
this.calls.push('change')
187+
},
188+
},
189+
template: `<var-switch :model-value="value" @update:model-value="handleUpdate" @change="handleChange" />`,
190+
})
191+
192+
await wrapper.find('.var-switch__block').trigger('click')
193+
194+
expect(calls).toStrictEqual(['update', 'change'])
195+
196+
wrapper.unmount()
197+
})
198+
167199
test('switch event not trigger', async () => {
168200
const clickFn = vi.fn()
169201
const changeFn = vi.fn()

0 commit comments

Comments
 (0)