Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

functional component wrapping with context.data causes v-model to update twice #8436

Closed
KaelWD opened this issue Jun 30, 2018 · 10 comments
Closed

Comments

@KaelWD
Copy link
Contributor

KaelWD commented Jun 30, 2018

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

KaelWD added a commit to vuetifyjs/vuetify that referenced this issue Jun 30, 2018
@posva
Copy link
Member

posva commented Jun 30, 2018

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 })

@KaelWD
Copy link
Contributor Author

KaelWD commented Jun 30, 2018

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?

@KaelWD
Copy link
Contributor Author

KaelWD commented Jul 22, 2018

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: vuetifyjs/vuetify#4460 (comment)

@wildan2711
Copy link

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

wildan2711 added a commit to wildan2711/vue that referenced this issue Jul 31, 2018
prevent double v-model update on functional components by not transforming model when
Ctor.options.functional is true

fix vuejs#8436
@wildan2711
Copy link

@KaelWD we attempt a fix here, should be enough: #8580

@posva
Copy link
Member

posva commented Jul 31, 2018

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

@wildan2711
Copy link

wildan2711 commented Jul 31, 2018

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

@KaelWD
Copy link
Contributor Author

KaelWD commented Jul 31, 2018

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

@wildan2711
Copy link

wildan2711 commented Aug 1, 2018

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.

@KaelWD
Copy link
Contributor Author

KaelWD commented Aug 19, 2018

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
    }
  }
}

yyx990803 added a commit that referenced this issue Dec 19, 2018
the condition is no longer necessary after reverting back to microtask
only nextTick implementation, and fix #8436
f2009 pushed a commit to f2009/vue that referenced this issue Jan 25, 2019
This happens when a component directly passes down its own data object
to a child component. Fix vuejs#8436.
f2009 pushed a commit to f2009/vue that referenced this issue Jan 25, 2019
the condition is no longer necessary after reverting back to microtask
only nextTick implementation, and fix vuejs#8436
aJean pushed a commit to aJean/vue that referenced this issue Aug 19, 2020
This happens when a component directly passes down its own data object
to a child component. Fix vuejs#8436.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants