javascript - How can I get Vue.js to be reactive for changes to dynamically added array properties? - Stack Overflow

In Vue.js, I have a data object with dynamically addededited properties that are themselves arrays. Fo

In Vue.js, I have a data object with dynamically added/edited properties that are themselves arrays. For example, the property starts out as follows:

data: function () {
    return {
        vals: {}
    };
}

And over time, through various button clicks, etc., vals may look like the following (with the actual property names and values being 100% dynamic based on a number of factors):

vals: {
    set1: [
        {
            prop1: 123,
            prop2: 'hello'
        },
        {
            prop1: 456,
            prop2: 'bye'
        }
    ],
    set2: [
        {
            prop3: 'Why?!',
            prop4: false
        }
    ]
}

As the array properties (i.e., set1 and set2) are changed, I want to be able to react to those changes.

For example, I may do something like the following in my code:

var prop = 'set1';

this.vals[prop].push({
    {
        prop1: 789,
        prop2: 'hmmm...'
    }
});

However, when I do that, the ponent is not updating (I presume because I am pushing an object onto the end of a subarray of an object; and Vue.js doesn't seem to track those changes).

I have been able to force the ponent to be reactive by doing this.$forceUpdate(); after the above push, but I imagine there has to be a more eloquent way of getting Vue.js to be reactive when it es to objects being pushed onto the end of object subarrays.

Does anyone know of a better way to try to do what I am trying to achieve? Thank you.

In Vue.js, I have a data object with dynamically added/edited properties that are themselves arrays. For example, the property starts out as follows:

data: function () {
    return {
        vals: {}
    };
}

And over time, through various button clicks, etc., vals may look like the following (with the actual property names and values being 100% dynamic based on a number of factors):

vals: {
    set1: [
        {
            prop1: 123,
            prop2: 'hello'
        },
        {
            prop1: 456,
            prop2: 'bye'
        }
    ],
    set2: [
        {
            prop3: 'Why?!',
            prop4: false
        }
    ]
}

As the array properties (i.e., set1 and set2) are changed, I want to be able to react to those changes.

For example, I may do something like the following in my code:

var prop = 'set1';

this.vals[prop].push({
    {
        prop1: 789,
        prop2: 'hmmm...'
    }
});

However, when I do that, the ponent is not updating (I presume because I am pushing an object onto the end of a subarray of an object; and Vue.js doesn't seem to track those changes).

I have been able to force the ponent to be reactive by doing this.$forceUpdate(); after the above push, but I imagine there has to be a more eloquent way of getting Vue.js to be reactive when it es to objects being pushed onto the end of object subarrays.

Does anyone know of a better way to try to do what I am trying to achieve? Thank you.

Share Improve this question edited May 17, 2019 at 20:52 HartleySan asked May 17, 2019 at 19:31 HartleySanHartleySan 7,84018 gold badges74 silver badges136 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5

Any time you're adding a new property to an object or changing a value within an array, you need to use Vue.set().

Vue.set(this.vals, prop, [ /* ... */ ])

Ideally, you should define all your properties up front so Vue doesn't have to invalidate puted properties depending on your data model's shape. Even if you have them set to null you should try to map out all the properties you expect your ponent to need.

Also, in your first code block, you have a colon after your return: which would evaluate to a label, meaning your data function isn't returning anything.

You could try something like this using lodash and a deep watcher..

More on deep watcher here

new Vue({
  el: "#app",
  methods: {
    setValue() {
      this.oldPeople = _.cloneDeep(this.people);
    }
  },
  mounted() {
    this.setValue();
  },
  el: "#app",
  data: {
    changed: null,
    people: [
      { id: 0, name: "Bob", age: 27 },
      { id: 1, name: "Frank", age: 32 },
      { id: 2, name: "Joe", age: 38 }
    ],
    oldPeople: []
  },
  watch: {
    people: {
      deep: true,
      handler(after, before) {
        // Return the object that changed
        let vm = this;
        let changed = after.filter(function(p, idx) {
          return Object.keys(p).some(function(prop) {
            return p[prop] !== vm.oldPeople[idx][prop];
          });
        });
        vm.setValue();
        this.changed = changed;
      },      
    }
  }
});
input {
  display: block;
}
<script src="https://cdnjs.cloudflare./ajax/libs/vue/2.1.6/vue.js"></script>
<script src="https://cdn.jsdelivr/lodash/4.17.2/lodash.min.js"></script>

<div id="app">
  <div>
    <input type="text" v-for="(person, index) in people" v-model="people[index].age" />
    <div v-if="changed !== null">
      You changed:<br/>{{ changed }}
    </div>
  </div>
</div>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745310956a4621995.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信