]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compat): allow v-model built in modifiers on component (#12654)
authorMark Florian <markrian@gmail.com>
Wed, 18 Jun 2025 12:53:25 +0000 (13:53 +0100)
committerGitHub <noreply@github.com>
Wed, 18 Jun 2025 12:53:25 +0000 (20:53 +0800)
close #12652

packages/runtime-core/src/componentEmits.ts
packages/vue-compat/__tests__/componentVModel.spec.ts

index db52bc88c333e02176c4da3409ea89177879250d..c03bead3a9280cf1e7bbf4a286123b877e09011b 100644 (file)
@@ -151,10 +151,14 @@ export function emit(
   }
 
   let args = rawArgs
-  const isModelListener = event.startsWith('update:')
+  const isCompatModelListener =
+    __COMPAT__ && compatModelEventPrefix + event in props
+  const isModelListener = isCompatModelListener || event.startsWith('update:')
+  const modifiers = isCompatModelListener
+    ? props.modelModifiers
+    : isModelListener && getModelModifiers(props, event.slice(7))
 
   // for v-model update:xxx events, apply modifiers on args
-  const modifiers = isModelListener && getModelModifiers(props, event.slice(7))
   if (modifiers) {
     if (modifiers.trim) {
       args = rawArgs.map(a => (isString(a) ? a.trim() : a))
index 7e4988287152c38405af237df9c8decebc70cc64..5ef1995473412e6a1ef97b8b016d566c119a54d7 100644 (file)
@@ -82,4 +82,62 @@ describe('COMPONENT_V_MODEL', () => {
       template: `<input :value="input" @input="$emit('update', $event.target.value)">`,
     })
   })
+
+  async function runTestWithModifier(CustomInput: ComponentOptions) {
+    const vm = new Vue({
+      data() {
+        return {
+          text: ' foo ',
+        }
+      },
+      components: {
+        CustomInput,
+      },
+      template: `
+      <div>
+        <span>{{ text }}</span>
+        <custom-input v-model.trim="text"></custom-input>
+      </div>
+      `,
+    }).$mount() as any
+
+    const input = vm.$el.querySelector('input')
+    const span = vm.$el.querySelector('span')
+
+    expect(input.value).toBe(' foo ')
+    expect(span.textContent).toBe(' foo ')
+
+    expect(
+      (deprecationData[DeprecationTypes.COMPONENT_V_MODEL].message as Function)(
+        CustomInput,
+      ),
+    ).toHaveBeenWarned()
+
+    input.value = ' bar '
+    triggerEvent(input, 'input')
+    await nextTick()
+
+    expect(input.value).toBe('bar')
+    expect(span.textContent).toBe('bar')
+  }
+
+  test('with model modifiers', async () => {
+    await runTestWithModifier({
+      name: 'CustomInput',
+      props: ['value'],
+      template: `<input :value="value" @input="$emit('input', $event.target.value)">`,
+    })
+  })
+
+  test('with model modifiers and model option', async () => {
+    await runTestWithModifier({
+      name: 'CustomInput',
+      props: ['foo'],
+      model: {
+        prop: 'foo',
+        event: 'bar',
+      },
+      template: `<input :value="foo" @input="$emit('bar', $event.target.value)">`,
+    })
+  })
 })