Ответы пользователя по тегу Vue.js
  • Как правильно типизировать vue generic components?

    @null_object
    const virtualizationContainer = ref<typeof VVirtualizationContainer | null>(null);


    playground

    6742b6fc6e199037664340.png
    Ответ написан
    3 комментария
  • Как можно вытащить типы пропсов из определения компонента?

    @null_object Автор вопроса
    type ComponentProps<ComponentDefinition> = ComponentDefinition extends { new (): { $props: infer P } } ? P : never;
    Ответ написан
    Комментировать
  • Как правильно отобразить компоненты в Components Tree Nuxt 3?

    @null_object
    Это стандартное поведение компонента <NuxtPage /> и не является проблемой, он внутри себя использует <RouterView /> из vue-router в который добавляется внутренняя логика Nuxt (например добавление Transitions если они указаны в настройках). Anonymous Component на самом деле - компонент RouteProvider, который занимается перерисовкой страниц. В общем, просто обертка фреймворка для роутинга.

    RouteProvider добавляется тут. Код самого провайдера можно тут посмотреть.
    Ответ написан
    Комментировать
  • Есть ли рекомендуемый порядок следования атрибутов во vue?

    @null_object
    Еще есть vue-eslint правило по порядку атрибутов
    Ответ написан
    Комментировать
  • Vue 3 Composition API как обратиться к функции через this.$refs?

    @null_object
    Чтобы напрямую вызывать методы инстанса компонента, нужно методы сделать публичными. Для этого есть expose в Options API и defineExpose для Composition API

    Child.vue
    <script setup>
    const foo = ref('foo')
    const bar = () => console.log('bar')
    
    defineExpose({
      foo,
      bar,
    })
    </script>

    Parent.vue
    <template>
      <Child ref="child" />
    </template>
    
    <script setup>
    const child = ref(null);
    
    onMounted(() => {
      console.log(child.value.foo)
      console.log(child.value.bar())
    })
    </script>


    Т. е. без доработок код из этого репозитория не заработает
    Ответ написан
    Комментировать
  • Как использовать хуки NUXT в модулях?

    @null_object
    Если нужны именно хуки
    const nuxtApp = useNuxtApp();
    
    const loadingStartHook = nuxtApp.hook('page:loading:start', () => {
      ...
    });
    
    const loadingFinishHook = nuxtApp.hook('page:loading:end', () => {
      ...
    });
    
    const unsubError = nuxtApp.hook('vue:error', () => ...)


    В какой-то из версий добавили встроенный композабл useLoadingIndicator . Это удобная обертка над этими хуками, можно в исходниках глянуть.

    Использовать достаточно просто
    const { progress, isLoading } = useLoadingIndicator();


    Тут можно посмотреть пример кастомного индикатора
    Ответ написан
    Комментировать
  • Почему подвисают дочерние компоненты vue?

    @null_object
    Тормозить начинает из-за большого количества нод в dom дереве. Решается использование "виртуального скролла", суть которого заключается в отрисовки только видимых элементов.

    Подробнее - https://www.patterns.dev/vanilla/virtual-lists

    Утилита для Vue - https://vueuse.org/core/useVirtualList/
    Ответ написан
    1 комментарий
  • Как правильно настроить refetch watch?

    @null_object
    <script setup lang="ts">
    import ModalDesktop from "~/components/modals/ModalDesktop.vue";
    
    interface Book {
      title: string;
      published_year: number;
      description: string;
      book_series: string;
      genre: string;
      authors: string;
      tag_id: string;
      id: string;
    }
    
    const token =
      "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIwY2Y5Nzk0Yi1jYjczLTR";
    
    const { data: books, refresh } = await useFetch<{ results: Book[] }>(
      "https://api.storage",
    );
    
    const { apiErrorHandler } = useErrorService();
    
    const selectedBook = ref<Book | null>(null);
    const showDeleteModal = ref(false);
    
    const modalVisible = computed(
      () => selectedBook.value !== null || showDeleteModal.value,
    );
    
    const openModal = (book: Book) => {
      selectedBook.value = book;
    };
    
    const closeModal = () => {
      selectedBook.value = null;
      showDeleteModal.value = false;
    };
    
    const deleteBook = async (book: Book) => {
      const { error } = await useFetch(`https://api.storage/${book.id}`, {
        method: "DELETE",
        headers: {
          Authorization: `Bearer ${token}`,
        },
      });
    
      if (error.value) {
        apiErrorHandler(error.value);
      } else {
        showDeleteModal.value = true;
        selectedBook.value = null;
      }
    };
    </script>


    <ModalDesktop v-if="modalVisible" @close="closeModal">
        <div class="px-space-s">
          <div v-if="selectedBook">
            <img
              :src="`https://api.storage/${selectedBook.cover_path}`"
              alt="Cover"
              class="w-[px] h-[100px] bg-center bg-cover"
            />
            <h4>{{ selectedBook.title }}</h4>
            <p><strong>Описание:</strong> {{ selectedBook.description }}</p>
            <p>
              <strong>Год публикации:</strong>
              {{ selectedBook.published_year }}
            </p>
            <p><strong>Серия:</strong> {{ selectedBook.book_series }}</p>
            <p><strong>Жанр:</strong> {{ selectedBook.genre }}</p>
            <p><strong>Автор:</strong> {{ selectedBook.authors }}</p>
            <p><strong>Тег:</strong> {{ selectedBook.tag_id }}</p>
            <p><strong>Id книги:</strong> {{ selectedBook.id }}</p>
          </div>
          <div v-if="showDeleteModal">
            <p>Книга успешно удалена!</p>
          </div>
          <div class="flex gap-x-space-s mt-space-s ml-auto">
            <button
              v-if="selectedBook"
              class="bg-blue-500 text-white p-space-xs pl-space-m pr-space-m rounded-medium hover:bg-blue-600"
              @click="deleteBook(selectedBook)"
            >
              Удалить
            </button>
          </div>
        </div>
      </ModalDesktop>
    Ответ написан
  • Vitest как скрыть каталог от coverage?

    @null_object
    export default defineConfig({
      plugins: [Vue()],
      test: {
        globals: true,
        environment: 'jsdom',
        coverage: {
          provider: 'v8',
          exclude: [...configDefaults.coverage.exclude, 'demo'],
        },
      },
    });
    Ответ написан
    Комментировать
  • Отображение рендеринг динамических компонентов на странице Vue3 Nuxt?

    @null_object
    Нужно явно импортировать ваши компоненты, так
    import {
      AddBookForm,
      AddTagsForm,
      AddAuthorsForm,
      AddSeriesForm,
      AddFilesForm
      AddFoldersForm,
    } from '#components'


    Либо использовать утилиту vue resolveComponent
    const buttons = [
      { formName: resolveComponent('AddBookForm'), label: 'Добавить книгу' },
      { formName: resolveComponent('AddTagsForm'), label: 'Добавить ТЕГ' },
      { formName: resolveComponent('AddAuthorsForm'), label: 'Добавить Автора' },
      { formName: resolveComponent('AddSeriesForm'), label: 'Добавить Серию' },
      { formName: resolveComponent('AddFilesForm'), label: 'Добавить Файл' },
      { formName: resolveComponent('AddFoldersForm'), label: 'Добавить Папку' },
    ];


    Из документации: https://nuxt.com/docs/guide/directory-structure/co...
    Ответ написан