Vite Hot Reload вызывает повторный запрос данных и дублирование данных в дочернем компоненте в Vue 3 Composition API

Вопрос или проблема

Я работаю над проектом на Vue 3, используя Composition API с TypeScript, и сталкиваюсь с проблемой, связанной с горячей заменой модулей (HMR) в Vite.

Описание проблемы:

Родительский компонент:

У меня есть переменная ref под названием data в родительском компоненте. Я передаю эти данные в дочерний компонент, используя двустороннюю привязку через v-model:data=”data”. В шаблоне родительского компонента у меня есть цикл v-for, который создает иконки для каждого элемента в data.

ParentComponent.vue:


<template>
  <ChildComponent v-model:data="data" />
  <div v-for="item in data" :key="item.id">
    <!-- Отображение иконки для каждого элемента -->
    <v-icon>mdi-blank-circle</icon>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
import Icon from './Icon.vue';

const data = ref([]);
</script>

Дочерний компонент: В дочернем компоненте я использую defineModel для определения модели данных. У меня есть асинхронная функция fetchData, которая получает данные и присваивает их data.value. Я вызываю onMounted(fetchData()), чтобы получить данные, когда компонент монтируется.

ChildComponent.vue:


<script setup lang="ts">
import { defineModel, onMounted } from 'vue';
import { getMyData } from './api';

const data = defineModel('data');

const fetchData = async () => {
  data.value = await getMyData();
};

onMounted(fetchData());
</script>

Каждый раз, когда Vite выполняет горячую перезагрузку в коде дочернего компонента (например, добавляя некоторые console.log в код), дочерний компонент повторно получает данные. Это повторное получение обновляет данные родителя, вызывая дублирование записей. В результате иконки в цикле v-for родительского компонента дублируются.

Проблема в том, что родительский компонент не перерисовывается, только дочерний компонент перерисовывается, и это вызывает следующее получение данных fetchData, и двусторонняя привязка обновляет значение в родительском компоненте с следующими данными. Например: 1. первое загрузка представления: 4 иконки 2. некоторые изменения в дочернем компоненте: 8 иконок И так далее… Когда я использую кнопку перезагрузки в браузере, все работает правильно, и у меня отображается 4 иконки.

  • Как я могу предотвратить повторное получение данных дочерним компонентом и вызвать дубликаты в родительском компоненте, когда происходит горячая перезагрузка Vite?

  • Существует ли рекомендуемый паттерн или лучшие практики в Vue 3 с Composition API и Vite для обработки этой ситуации?

Любая информация или предложения будут очень признательны!

Ответ или решение

Устранение проблемы повторного извлечения данных при горячей замене модулей в Vue 3 с использованием Vite

В рамках вашего проекта на Vue 3 с использованием Composition API и TypeScript вы столкнулись с проблемой, когда горячая замена модулей (HMR) в Vite вызывает повторное извлечение данных в дочернем компоненте. Это, в свою очередь, приводит к дублированию иконок в родительском компоненте, поскольку данные обновляются каждый раз, когда ребенок обновляется. Давайте разберем, как можно решить эту проблему и какие лучшие практики использовать для предотвращения подобных ситуаций в будущем.

Проблема описания

  1. Структура компонента:

    • В родительском компоненте у вас есть переменная data, которая передается в дочерний компонент через двустороннее связывание v-model.
    • Дочерний компонент выполняет асинхронную функцию fetchData, которая получает данные и присваивает их data.value при монтировании компонента.
  2. Симптомы проблемы:

    • При каждом изменении в дочернем компоненте, связанном с HMR, функция fetchData срабатывает, что приводит к повторной загрузке данных и удвоению значений в родительском компоненте.

Решение проблемы

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

  1. Избегайте вызова fetchData без условий:
    Вместо того, чтобы вызывать fetchData непосредственно в onMounted, установите флаг, который будет отслеживать, загружались ли данные уже:

    <script setup lang="ts">
    import { defineModel, onMounted } from 'vue';
    import { getMyData } from './api';
    
    const data = defineModel('data');
    
    // Добавим флаг загрузки
    let isDataFetched = false;
    
    const fetchData = async () => {
       if (!isDataFetched) {
           data.value = await getMyData();
           isDataFetched = true; // Установим флаг, чтобы данные не загружались повторно
       }
    };
    
    onMounted(fetchData);
    </script>
  2. Используйте v-if для условного рендеринга:
    Добавьте условный рендеринг в родительском компоненте, чтобы отслеживать, была ли загружена информация, и предотвращать рендеринг дубликатов:

    <template>
       <ChildComponent v-model:data="data" />
       <div v-if="data.length">
           <div v-for="item in data" :key="item.id">
               <v-icon>mdi-blank-circle</v-icon>
           </div>
       </div>
    </template>
  3. Отказ от двустороннего связывания при HMR:
    Рассмотрите возможность использования однонаправленного потока данных. Вместо использования v-model, можно просто передать данные в дочерний компонент как :data="data", а изменения отправлять через события. Это может снизить вероятность возникновения проблем при HMR.

  4. Оптимизация HMR:
    Если вы продолжаете сталкиваться с явлениями HMR, попробуйте отключить HMR для определенных частей вашего приложения во время разработки, чтобы изучить взаимодействие компонентов более детально и понять, в чем происходит проблема.

Лучшие практики

  • Четкое разделение данных и представления: Убедитесь, что ваш компонент получает только необходимые данные и обрабатывает их минимально.
  • Управление состоянием: Для более комплексных приложений рассмотрите использование библиотек управления состоянием, таких как Vuex или Pinia, которые помогут избежать проблем с дублированием данных и сложностью передачи их между компонентами.
  • Тестирование в режиме разработки: Регулярно тестируйте вашу логику в режиме разработки, чтобы убедиться, что изменения в компонентах не влияют на результаты работы.

Заключение

Решение проблемы повторного извлечения данных в вашем проекте на Vue 3 с использованием Vite возможно через правильную организацию кода и использование флагов состояния. Надеюсь, что предложенные подходы и практические советы помогут вам эффективно справляться с данной проблемой и улучшить архитектуру вашего приложения.

Оцените материал
Добавить комментарий

Капча загружается...