Skip to content

Commit cb14b86

Browse files
authored
fix(compat): allow v-model built in modifiers on component (#12654)
close #12652
1 parent 9818456 commit cb14b86

File tree

2 files changed

+64
-2
lines changed

2 files changed

+64
-2
lines changed

packages/runtime-core/src/componentEmits.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,14 @@ export function emit(
151151
}
152152

153153
let args = rawArgs
154-
const isModelListener = event.startsWith('update:')
154+
const isCompatModelListener =
155+
__COMPAT__ && compatModelEventPrefix + event in props
156+
const isModelListener = isCompatModelListener || event.startsWith('update:')
157+
const modifiers = isCompatModelListener
158+
? props.modelModifiers
159+
: isModelListener && getModelModifiers(props, event.slice(7))
155160

156161
// for v-model update:xxx events, apply modifiers on args
157-
const modifiers = isModelListener && getModelModifiers(props, event.slice(7))
158162
if (modifiers) {
159163
if (modifiers.trim) {
160164
args = rawArgs.map(a => (isString(a) ? a.trim() : a))

packages/vue-compat/__tests__/componentVModel.spec.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,62 @@ describe('COMPONENT_V_MODEL', () => {
8282
template: `<input :value="input" @input="$emit('update', $event.target.value)">`,
8383
})
8484
})
85+
86+
async function runTestWithModifier(CustomInput: ComponentOptions) {
87+
const vm = new Vue({
88+
data() {
89+
return {
90+
text: ' foo ',
91+
}
92+
},
93+
components: {
94+
CustomInput,
95+
},
96+
template: `
97+
<div>
98+
<span>{{ text }}</span>
99+
<custom-input v-model.trim="text"></custom-input>
100+
</div>
101+
`,
102+
}).$mount() as any
103+
104+
const input = vm.$el.querySelector('input')
105+
const span = vm.$el.querySelector('span')
106+
107+
expect(input.value).toBe(' foo ')
108+
expect(span.textContent).toBe(' foo ')
109+
110+
expect(
111+
(deprecationData[DeprecationTypes.COMPONENT_V_MODEL].message as Function)(
112+
CustomInput,
113+
),
114+
).toHaveBeenWarned()
115+
116+
input.value = ' bar '
117+
triggerEvent(input, 'input')
118+
await nextTick()
119+
120+
expect(input.value).toBe('bar')
121+
expect(span.textContent).toBe('bar')
122+
}
123+
124+
test('with model modifiers', async () => {
125+
await runTestWithModifier({
126+
name: 'CustomInput',
127+
props: ['value'],
128+
template: `<input :value="value" @input="$emit('input', $event.target.value)">`,
129+
})
130+
})
131+
132+
test('with model modifiers and model option', async () => {
133+
await runTestWithModifier({
134+
name: 'CustomInput',
135+
props: ['foo'],
136+
model: {
137+
prop: 'foo',
138+
event: 'bar',
139+
},
140+
template: `<input :value="foo" @input="$emit('bar', $event.target.value)">`,
141+
})
142+
})
85143
})

0 commit comments

Comments
 (0)