Исправляем ошибку "Vue 2 – Mutating props vue-warn" в Vue.JS

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для предотвращения предупреждений Vue, связанных с мутацией свойств, создайте в данных дочернего компонента локальную копию свойства и модифицируйте её. Используйте вычисляемые свойства с getter'ами и setter'ами для управления изменениями. Для обратного взаимодействия с родительским компонентом применяйте события.

JS
Скопировать код
// Дочерний компонент
data() {
  return {
    localCopy: this.propValue
  };
},
props: ['propValue'],
computed: {
  value: {
    get() {
      return this.localCopy;
    },
    set(newValue) {
      this.localCopy = newValue;
      this.$emit('input', newValue);
    }
  }
}

Применяйте в родительском компоненте модификатор .sync для двусторонней привязки данных или обрабатывайте события вручную.

JS
Скопировать код
// Родительский компонент
<child-component :prop-value.sync="valueFromParent"></child-component>
<child-component :prop-value="valueFromParent" @input="valueFromParent = $event"></child-component>
Кинга Идем в IT: пошаговый план для смены профессии

Осознанное управление модификацией свойств

Vue.js не приветствует непосредственное изменение свойств, поскольку это нарушает концепцию одностороннего потока данных.

Клонирование свойств для изменения в них

Безопасно изменять можно лишь клонированное свойство, создав начальное значение данных как локальной переменной, равное значению свойства.

JS
Скопировать код
data() {
  return {
    mutableProp: JSON.parse(JSON.stringify(this.propValue))
  };
}

Vuex для управления сложным состоянием

Use Vuex to manage the common state between components, which offers a centralized store with state change rules.

Использование вычисляемых свойств

Вычисляемые свойства с сеттером позволяют корректно уведомлять родительский компонент об изменениях:

JS
Скопировать код
computed: {
  propModel: {
    get() {
      return this.propValue;
    },
    set(value) {
      this.$emit('update:propValue', value);
    }
  }
}

Когда возможно редактировать свойство

Напрямую менять свойства не стоит даже при простой структуре данных, так как это может привести к нежелательным последствиям.

Реактивность с неизменяемыми свойствами

Рассматривайте свойства как неизменяемые и используйте реактивные функции для контроля изменений.

JS
Скопировать код
methods: {
  updateValue(newVal) {
    if (newVal !== this.propValue) {
      this.mutableProp = newVal;
      this.$emit('prop-change', newVal);
    }
  }
}

Практический пример в действии

При создании пользовательского компонента ввода, которому передается значение через свойство value, создавайте события input для поддержки v-model в родительском компоненте.

JS
Скопировать код
// Пользовательский компонент ввода
props: ['value'],
computed: {
  inputValue: {
    get() {
      return this.value;
    },
    set(value) {
      this.$emit('input', value);
    }
  }
}
// Родительский компонент
<custom-input v-model="parentValue"></custom-input>

Визуализация

Воспринимайте прямое изменение свойств как вредное воздействие на функционирование системы. Использование вычисляемых свойств своеобразная защита от некорректной модификации.

Реактивность и хуки жизненного цикла

Оптимизация посредством наблюдателей

Для отслеживания изменений свойств и последующей реакции на них используйте наблюдатели.

JS
Скопировать код
watch: {
  propValue(newValue) {
    this.doSomethingWith(newValue);
  }
}

Синхронизация жизненного цикла с реактивностью

Начальное состояние копий свойств инициализируйте при создании или монтировании компонента.

JS
Скопировать код
mounted() {
  this.mutableProp = JSON.parse(JSON.stringify(this.propValue));
}

Советы по написанию понятного и поддерживаемого кода

Важность соглашений об именовании

Воспользуйтесь четкой конвенцией именования, чтобы избежать путаницы.

JS
Скопировать код
data() {
  return {
    internalValue: this.propValue
  };
}

Ясность кода и комментариев

Оставляйте комментарии к коду, объясняя особенности работы со свойствами.

JS
Скопировать код
data() {
  return {
    internalValue: JSON.parse(JSON.stringify(this.propValue))
  };
}

Цикл “пересмотр-рефакторинг-повторение”

Регулярно пересматривайте и улучшайте код, следите за рекомендациями Vue.

Полезные материалы

  1. Свойства | Vue.js: официальное руководство по работе со свойствами.
  2. Вычисляемые свойства | Vue.js: подробности про использование наблюдателей.
  3. События компонентов | Vue.js: как правильно генерировать события в Vue.
  4. Справочник API | Vue.js: подробный справочник по API свойств Vue.
  5. Учебник | DigitalOcean: необходимые знания для работы с мутациями свойств.
  6. Что такое Vuex? | Vuex: гайд по управлению состоянием в Vue с помощью Vuex.