Vue: functional component wrapping with context.data causes v-model to update twice

Created on 30 Jun 2018  路  10Comments  路  Source: vuejs/vue

Version

2.5.16

Reproduction link

https://codepen.io/anon/pen/LrMKMg?editors=1011

Steps to reproduce

type in the input

What is expected?

'input' should be logged once

What is actually happening?

'input' is logged twice


Uncomment delete ctx.data.model and it works fine

Original pen using vuetify: https://codepen.io/anon/pen/QxzXYK?editors=1011

Most helpful comment

Here's my solution until this is fixed in vue:

function dedupeModelListeners (data: VNodeData): void {
  if (data.model && data.on && data.on.input) {
    if (Array.isArray(data.on.input)) {
      const i = data.on.input.indexOf(data.model.callback)
      if (i > -1) data.on.input.splice(i, 1)
    } else {
      delete data.on.input
    }
  }
}

All 10 comments

Yeah, both shouldn't be passed, only model. Maybe we should remove the domProps.value and on.input if there's a model in the context
You need to pass model to data:

return h('base-input', { model: ctx.data.model })

I thought v-model was supposed to be syntactic sugar, why does it have a separate undocumented property on VNodeData? Does it make a difference if I pass through props and on instead? Should we be using model in all other calls to createElement? Why does data.model.expression exist? Is there a way to see data.model.expression in non-functional components too? Is this example only intended for native elements, because it clearly doesn't work with components?

Turns out someone was relying on data.model.expression, but I can't find a way to allow that without breaking a bunch of other shit: https://github.com/vuetifyjs/vuetify/issues/4460#issuecomment-406870878

Yes, us included. We rely on it to inject server side validation on a Vuetify input.

@KaelWD we attempt a fix here, should be enough: https://github.com/vuejs/vue/pull/8580

I'm worried that removing the listener and prop binding like in #8580 ends up in a less flexible approach: what if users want to use the listener + binding instead of model?
It would be great if we can check major ui libraries for Vue and see if this doesn't break them or make sure they're prepared for the change

Do you mean using @input and value on a component instead of v-model?

Or using v-model and @input at the same time. (yeah I know you shouldn't but I've seen it a fair bit)

Tested it on #8580, it works for all 3 cases (without double update):

  • v-model only
  • @input and :value
  • v-model and @input

Maybe later I should write some unit tests to demonstrate it.

Here's my solution until this is fixed in vue:

function dedupeModelListeners (data: VNodeData): void {
  if (data.model && data.on && data.on.input) {
    if (Array.isArray(data.on.input)) {
      const i = data.on.input.indexOf(data.model.callback)
      if (i > -1) data.on.input.splice(i, 1)
    } else {
      delete data.on.input
    }
  }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

yyx990803 picture yyx990803  路  36Comments

karevn picture karevn  路  36Comments

smolinari picture smolinari  路  116Comments

karevn picture karevn  路  42Comments

yyx990803 picture yyx990803  路  48Comments