将观察者添加到动态创建的对象

时间:2019-08-30 10:34:11

标签: javascript vue.js

在组件工作的某个时间点,其从原语的值之一变成了对象。该对象是动态分配的带有值的字段。有必要跟踪这些值的变化。

重现该问题的简化代码:

const fields = ['name', 'age'];

const app = new Vue({
  el: '#app',
  data() {
    return {
      value: '',
    };
  },
  watch: {
    value: function() {
      console.log('Global: Value changed');
    },
  },
  mounted() {
    this.value = '111';
    this.value = {};
    fields.forEach(field => {
      this.value[field] = '';
    });

    this.$watch('value', callback, { deep: true });
    function callback() {
      console.log('Callback: Value changed');
    }

    this.$nextTick(() => {
      this.value.name = 'Max';
      this.value.age = 30;
      console.log(this.value)
    });
  },
});
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>

<div id="app"></div>

3 个答案:

答案 0 :(得分:1)

关键行是this.value = ...。这就是使对象具有反应性的点,并且所有属性都必须在该点存在。

在这里,我已经对该部分进行了调整,以在将对象分配给this.value之前添加属性。

const fields = ['name', 'age'];

const app = new Vue({
  el: '#app',
  data() {
    return {
      value: '',
    };
  },
  watch: {
    value: function() {
      console.log('Global: Value changed');
    },
  },
  mounted() {
    this.value = '111';

    const value = {}

    fields.forEach(field => {
      value[field] = '';
    });

    this.value = value;

    this.$watch('value', callback, { deep: true });
    function callback() {
      console.log('Callback: Value changed');
    }

    this.$nextTick(() => {
      this.value.name = 'Max';
      this.value.age = 30;
      console.log(this.value)
    });
  },
});
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>

<div id="app"></div>

或者,您可以稍后使用this.$set进行设置:https://vuejs.org/v2/api/#vm-set

答案 1 :(得分:1)

Vue.$set(object, key, value)在这里可能会有所帮助:

const fields = ['name', 'age'];

const app = new Vue({
  el: '#app',
  data() {
    return {
      value: '',
    };
  },
  watch: {
    value: {
      handler: function(value) {
        console.log('Global: Value changed', value);
      },
      deep: true
    }
  },
  mounted() {
    let value = {};
    fields.forEach(field => {
      value[field] = '';
    });

    this.$set(this, 'value', value);

    this.$nextTick(() => {
      this.value.name = 'Max';
      this.value.age = 30;
      console.log(this.value)
    });
  },
});
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>

<div id="app"></div>

答案 2 :(得分:1)

这称为反应性警告

https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

因此,要解决此问题,您可以导入vue

import Vue from 'vue'

,然后要更改对象的值

fields.forEach(field => {
  //this.value[field] = ''; // instead of this
    Vue.set(this.value, 'field', '')
});

OR

this.$set(this.value, 'field', '')