Что такое потеря реактивности во Vue

Ответ

Потеря реактивности в Vue происходит, когда изменения данных не вызывают обновления интерфейса. Основные причины:

  1. Добавление новых свойств в объект:
data() {
  return { user: { name: 'Alice' } }
}
// Не реактивно:
this.user.age = 25
// Реактивно:
this.$set(this.user, 'age', 25)
  1. Изменение длины массива:
// Не реактивно:
this.items.length = 0
// Реактивно:
this.items = []
  1. Индексы массива:
// Не реактивно:
this.items[0] = newValue
// Реактивно:
this.$set(this.items, 0, newValue)

Для объектов Vue использует Object.defineProperty (в Vue 2) или Proxy (в Vue 3), которые не отслеживают динамически добавляемые свойства. Все данные для реактивности должны быть объявлены изначально в data().

Ответ 18+ 🔞

Да ты посмотри, какой народ-то у нас пошёл! Сидит, значит, на Vue, а у него хуйня какая-то творится — данные поменял, а интерфейс нихрена не обновился, как будто в рот ему чих-пых! Ну, слушай, давай разбираться, где тут собака зарыта, а то ведь реально можно с ума сойти.

Первая причина, от которой у меня волосы дыбом встают — это когда ты новые свойства в объект пихаешь, как последний распиздяй. Смотри, объявил ты объект:

data() {
  return { user: { name: 'Alice' } }
}

И думаешь: «О, сейчас я ему age добавлю, и всё будет пиздец как реактивно!»

// НЕ РЕАКТИВНО, БЛЯДЬ! ВОТ ТУТ-ТО ТЫ И ПОПАЛСЯ!
this.user.age = 25

А Vue смотрит на это и такой: «Мужик, ты чё, охренел? Я про это свойство нихуя не знаю, я его не отслеживаю!». И интерфейс стоит колом, как истукан. Надо делать по-человечески, через $set:

// А вот так — РЕАКТИВНО, красава! Vue теперь в курсе дела.
this.$set(this.user, 'age', 25)

Вторая история — длину массива менять. Ну, представим, ты решил массив обнулить, чтоб по-быстрому:

// НЕ РЕАКТИВНО! Это пиздец, какой тупой способ!
this.items.length = 0

Vue на это среагирует примерно так: «Ну и хуй с тобой». Массив-то пустой, а вот реактивность на такое изменение нихуя не сработает. Правильно — присвоить новый пустой массив:

// РЕАКТИВНО! Вот теперь Vue обновится, как миленький.
this.items = []

Третий номер нашей программы — попытка поменять элемент массива по индексу. О, это классика, ёпта!

// НЕ РЕАКТИВНО! Опять ты в лужу сел, дружок.
this.items[0] = newValue

Vue опять нихуя не увидит. Надо опять звать на помощь $set:

// РЕАКТИВНО! Теперь всё в ажуре.
this.$set(this.items, 0, newValue)

А знаешь, в чём корень всего этого зла, блядь? Внутри Vue 2 использует Object.defineProperty, а в третьей версии — Proxy. И эта штука, она как хитрая жопа — не отслеживает свойства, которые появились потом, из ниоткуда. Поэтому все данные, которые должны быть реактивными, надо объявлять сразу, в data(), как порядочные люди. Не объявил — потом не жалуйся, что у тебя всё ебётся и не работает.

Вот и весь сказ, блядь. Запомни эти три пункта, и жить станет проще, а интерфейс будет обновляться, а не висеть, как манда с ушами.