Реактивность props

В Vue props представляют собой основной механизм передачи данных от родительских компонентов к дочерним. Понимание их реактивности критично для корректного построения компонентов и написания тестов с использованием Vue Test Utils.

Основы реактивности props

props в Vue являются реактивными. Это означает, что любые изменения их значений в родительском компоненте автоматически отражаются в дочернем, если дочерний компонент использует эти props.

Пример базового компонента:

<template>
  <div>{{ message }}</div>
</template>

<script>
export default {
  props: {
    message: {
      type: String,
      required: true
    }
  }
}
</script>

Если родительский компонент изменяет значение message, это изменение автоматически отразится в шаблоне дочернего компонента.

Важно помнить, что реактивность работает только в рамках реактивной системы Vue. Присваивание нового объекта или массива через props не меняет ссылку родительской переменной, а лишь обновляет внутреннее представление в дочернем компоненте.

Тестирование реактивности props с Vue Test Utils

Vue Test Utils предоставляет методы для монтирования компонентов и управления их props в тестовой среде. Основные методы:

  • mount() — создаёт полный экземпляр компонента с рендерингом DOM.
  • shallowMount() — создаёт компонент без рендеринга дочерних компонентов, полезно для изоляции.
  • setProps() — изменяет props после монтирования и запускает реактивное обновление.

Пример теста реактивности:

import { mount } from '@vue/test-utils';
import MyComponent from '@/components/MyComponent.vue';

test('reactive props update DOM', async () => {
  const wrapper = mount(MyComponent, {
    props: { message: 'Initial' }
  });

  expect(wrapper.text()).toBe('Initial');

  await wrapper.setProps({ message: 'Updated' });
  expect(wrapper.text()).toBe('Updated');
});

Здесь ключевой момент — асинхронность обновлений. Метод setProps() возвращает промис, который разрешается после завершения реактивного обновления DOM. Использование await гарантирует корректную проверку состояния компонента после изменения props.

Ограничения и особенности

  1. Props должны оставаться неизменяемыми внутри компонента. Vue не запрещает изменение объекта, переданного через props, но это нарушает концепцию однонаправленного потока данных. Для тестов это значит, что проверка реактивности должна идти через setProps() или родительский компонент.

  2. Реактивность вложенных объектов. Если prop — объект или массив, изменение вложенного свойства не всегда триггерит обновление шаблона, если Vue не наблюдает за этим свойством. Пример:

props: {
  user: Object
}

// В тесте
await wrapper.setProps({ user: { name: 'Alice' } });

Если модифицировать только user.name напрямую (wrapper.props().user.name = 'Bob'), Vue не гарантирует обновления DOM. Рекомендуется использовать новый объект или setProps().

  1. Асинхронные вычисляемые свойства. Компоненты могут иметь вычисляемые свойства, зависящие от props. Их реактивность также тестируется через setProps(), учитывая, что любое обновление props может изменить вычисляемое значение и рендер.

Проверка событий при изменении props

Иногда важно протестировать реакцию компонента на изменение props через события или методы. Например:

test('triggers method on prop change', async () => {
  const wrapper = mount(MyComponent, { props: { count: 0 } });
  const spy = jest.spyOn(wrapper.vm, 'handleCountChange');

  await wrapper.setProps({ count: 5 });
  expect(spy).toHaveBeenCalledWith(5);
});

Здесь показано, что метод handleCountChange вызывается при изменении props. Это важно для компонентов с побочными эффектами.

Практические рекомендации для тестирования реактивности

  • Использовать setProps() для всех изменений props после монтирования.
  • Всегда дожидаться завершения асинхронного обновления с await.
  • Для вложенных объектов заменять объект полностью, а не модифицировать свойства напрямую.
  • Проверять как DOM, так и реакцию методов или вычисляемых свойств на изменения props.
  • Комбинировать с nextTick() при необходимости, если тест проверяет несколько последовательных реактивных обновлений.

Выводы по реактивности props в тестах

  • props остаются источником правды для дочернего компонента и автоматически обновляют шаблон при изменении.
  • Vue Test Utils предоставляет инструменты для корректного управления и тестирования этих изменений.
  • Понимание границ реактивности и асинхронного характера обновлений — ключ к надежным тестам компонентов.

Реактивность props — фундаментальное свойство Vue, и её правильное тестирование позволяет создавать стабильные и предсказуемые компоненты, где данные обновляются строго по однонаправленному потоку.