Как запустить функцию при изменении каких-либо данных в объекте с помощью Vuejs?

#javascript #object #vue.js #vuejs2

#javascript #объект #vue.js #vuejs2

Вопрос:

Итак, у меня есть следующие данные, и моя цель — пересчитывать результаты пользователя каждый раз, когда данные в этом объекте изменяются. Вот данные.

 data() {
  return {     
    test: 0, 
    userData: {
      sex: null,
      age: null,
      feet: null,
      inches: null,
      activity: null,
      goal: null,
    },
  }
}
  

Теперь я попытался реализовать как watch, так и computed, но это приводит к тому, что Vue не замечает, когда изменяются отдельные элементы в объекте. Однако, если я извлекаю некоторые данные из объекта, он замечает изменение.

Вот что я пробовал для watch:

 watch: {
  userData: function () {
    console.log("Changed");
  }
}
  

В результате в консоли ничего не было.

Для computed я попробовал следующее:

 computed: {
  results: function () {
    console.log(this.userData);
    return this.userData.sex;
  }
}
  

Но снова в консоли ничего не было напечатано.

Если бы я попытался с помощью тестовой переменной:

 watch: {
  test: function () {
    console.log("Changed");
  }
}
  

При изменении переменной вывод изменился бы. Итак, это работает, потому что это не объект.

Любая помощь была бы очень признательна. Опять же, цель состоит в том, чтобы пересчитывать результаты всякий раз, когда изменяются какие-либо пользовательские данные.

Комментарии:

1. Возможно, вы захотите использовать Vue.set и Vue.delete , поскольку Vue не обладает реактивностью для вложенных объектов: vuejs.org/v2/api/#Vue-set

2. @match Однако, как я могу запустить функцию при изменении с помощью этого подхода?

3. Просто убедитесь, что любые изменения, которые использует объект Vue.set (а не прямое манипулирование объектом — это позволит Vue «заметить», что это изменилось, и ваша watch функция будет запущена.

4. @match Итак, для sex я мог бы использовать что-то вроде этого? Vue.set( userData, sex, male ) . И будет ли теперь работать тот же наблюдатель?

5. Да — это должно позволить Vue «увидеть» изменение. Возможно, вы также захотите изучить Vuex как лучший способ обработки изменений состояния.

Ответ №1:

Вот один из способов сделать это. Вам нужно (как упоминал @match) использовать Vue.set() или vm.$set() . Я обнаружил, что также необходимо обновить ваше свойство watcher до userData.sex .

 new Vue({
  el: "#app",
  data: {  
    status: '', 
    userData: {
      sex: ''
    },
  },
  methods: {
    updateValues(){
      // Or Vue.set()
      this.$nextTick( function(){
        const newUserData = Object.assign({}, this.userData);
        newUserData.sex = "Male";
        this.userData = newUserData;
      });
    }
  },
  watch: {
    userData: function (v) {
      this.status  = "userData Changed";
    },
    'userData.sex': function (v) {
      this.status  = "nuserData.sex Changed";
    }
  }
})  
 <script src="https://cdn.jsdelivr.net/npm/vue@2.6.8/dist/vue.min.js"></script>
<div id="app">
  <pre v-text="'userData.sex = '   userData.sex"></pre>
  <pre v-text="status"></pre>
  <button @click="updateValues()">
    Change Sex
  </button>
</div>  

Редактировать:

Повторное назначение всего объекта userData запускает watch.userData .

Комментарии:

1. обнаружило бы это изменение, если бы я просматривал userData? Я хочу запускать одну функцию для любого изменения пользовательских данных.

2. @AnthonySette Я обновил код, чтобы заставить это работать, требуется переназначение всего userData объекта.

Ответ №2:

Вы на самом деле используете results свойство (например, в вашем шаблоне)? Вычисленные свойства не пересчитываются, если они не используются.

В отличие от того, что говорит @match, я сомневаюсь, что у вас проблема с реактивностью, поскольку вы не добавляете и не удаляете свойства (они уже существуют в ваших данных, поэтому они уже реактивные).

Комментарии:

1. Я не был, позвольте мне попробовать!

2. Это сработало, вычисленный, который я написал, работал, но у меня не было результатов на странице, поэтому он не был запущен!