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

Deep props change: v-model vs. this.$set() vs. Object.assign() #6670

Closed
mityukov opened this issue Sep 22, 2017 · 4 comments
Closed

Deep props change: v-model vs. this.$set() vs. Object.assign() #6670

mityukov opened this issue Sep 22, 2017 · 4 comments

Comments

@mityukov
Copy link

Version

2.4.1

Reproduction link

https://jsfiddle.net/spo7ywbh/

Steps to reproduce

Consider three examples:

1. v-model:

<template>
  <input type="checkbox" v-model="value[slug][userId]">
</template>

2. this.$set():

<template>
  <input type="checkbox" :checked="value[slug][userId]" @change="update(slug, userId)">
</template>

<script>
// ...
  methods: {
    update(slug, userId) {
      this.$set(this.value[slug], userId, !! event.target.checked);
    }
  },
// ...
</script>

3. Object.assign():

<template>
  <input type="checkbox" :checked="value[slug][userId]" @change="update(slug, userId)">
</template>

<script>
// ...
  methods: {
    update(slug, userId) {
      let obj = this.value;
      obj[slug][userId] = !! event.target.checked;
      this.value = Object.assign({}, this.value, obj);
    }
  },
// ...
</script>

What is expected?

I expect all three ways to work as expected. I.e.: if I look at value structure in the Vue dev tools, I can see its "leaves" to toggle between true and false as I check/uncheck checkboxes.

What is actually happening?

In fact, only the third way works as expected. Moreover, 2nd way is also working, but… sometimes, which is unacceptable :-(


Maybe it's me getting the whole "reactivity" thing wrongly… However, in the documentation this.$set() is especially "promoted" in this matter.

@yyx990803
Copy link
Member

$set only creates reactivity for that specific property, but your value object's inner structure was created in created hook without any reactivity. Move the code in your created hook into the data function itself so that whole value is properly reactive: https://jsfiddle.net/spo7ywbh/1/

@mityukov
Copy link
Author

mityukov commented Sep 26, 2017

I think that I'll have to find a way to construct the value in created() hook. Today, there's currentValue, passed via the props. Tomorrow, it may be requested from a server.

Question: can I use this.$set() to build the value while in created()? Will it be reactive?

--

Cool! I can even use v-model after this "re-design":
https://jsfiddle.net/npe92746/2/

(after using this.$set() while building this.value inside created())

@ivankarpey
Copy link

ivankarpey commented Jun 26, 2018

@yyx990803 I do realize that to properly have tracking for nested substructure it's required to convert props to a data, however, I don't really understand why overwriting the whole prop object (with Object.Assign for instance) inside component itself still cause reactive changes, but changing only a property - don't. My question on the StackOverflow as an example

@rostber
Copy link

rostber commented Feb 21, 2020

You can solve the problem with a deep value like this:
1. v-model:

<template>
  <input type="checkbox" v-model="value[slug][userId]" @input="$forceUpdate()">
</template>```

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

No branches or pull requests

4 participants