Confusion on and additional subtleties of v-bind.sync
See original GitHub issueThis is a complex topic and I might be missing something, but…
I think the docs at https://vuejs.org/v2/guide/components-custom-events.html#sync-Modifier could use three updates:
- There should be some mention that
.sync
can only be used when the expression is a proper lvalue/reference. For instance::title.sync="title"
:title.sync="title + '!'"
won’t work. It will generate an error along the lines of:
SyntaxError: Left hand side of operator '=' must be a reference.
Fiddle: https://jsfiddle.net/davidkhess/vs1rxwLh/3/
- When an object is used with v-bind, I think it would be worth mentioning that unlike normal bindings with .sync that update the referenced key on the Vue instance’s data (i.e. 1. above), in this case it is only going to update that literal key on the object used in the v-bind.
At least, this is my understanding of things looking at the implementation:
https://github.com/vuejs/vue/commit/3965e5053a7d2f22e90f81d4a153d65c1c670897
Fiddle: https://jsfiddle.net/davidkhess/vs1rxwLh/33/
- Re: this warning:
Using v-bind.sync with a literal object, such as in v-bind.sync=”{ title: doc.title }”, will not work. If you want to include multiple, unrelated data properties in the same v-bind.sync, we recommend creating a computed property that returns an object.
I think it would help to explain why a literal object doesn’t work. I believe the reason is that a literal object is not going to be reactive since it isn’t attached to a Vue instance’s data and therefore the param on the child component will not be updated when the object’s attribute is updated. The resolution is to make sure it is reactive and a computed property will do that.
However, I think the recommended solution of a computed property creates more confusion since based on 2. above, the $emit("update:...")
is going to update an attribute of the object returned by the computed property which goes against the spirit of a computed property and is not easily accessible. I think it might be more useful to recommend attaching a params object to the parent’s data so that the parent component can more easily watch
an attribute of the params object for changes from the child component if needed.
EDIT: I’m not able to get the computed approach to work https://jsfiddle.net/davidkhess/vs1rxwLh/22/
I think it’s because an object returned from a computed is not reactive.
Issue Analytics
- State:
- Created 5 years ago
- Comments:7 (6 by maintainers)
Top GitHub Comments
@davidkhess I’ve just added a special note about how
v-bind
with the.sync
modifier cannot be used with expressions, so that should improve the situation as much as we can for now.I agree that this is probably the right direction for alleviating this confusion. 🙂 We are actually thinking about moving this behavior to the
v-model
API for Vue 3 (e.g.v-model:prop="title"
instead ofv-bind:title.sync="title"
), since it changesv-bind
’s behavior so drastically and really has more in common withv-model
. That’s a change we should also be able to backport to Vue 2 (while still maintainingv-bind.sync
behavior so that existing apps don’t break).@peckomingo That’s correct, though it should be possible to fix that. A feature request issue on the vuejs/vue repo would be welcome. 🙂
It seems also not possible to use
v-bind
andv-bind.sync
on the same component. Let’s say I have an object which all of its properties should two-way-bind and an object with all of its properties are normal one-way. Is there something I have overlooked or is it just not possible to use both at once?