Ошибка типа: преобразование циклической структуры в JSON при доступе к данным $slot из дочернего компонента в VueJS 3

Проблема: <pre>{{ $slots.title() }}</pre> не распечатывает ожидаемый объект.

Мой родительский компонент

МодальныйView.vue

<script setup>
import { ref } from 'vue'
import Modal from '@/components/Modal.vue'
import { btnStyleDark } from '@/styles/tailwindStyles'

const showModal = ref(false)
</script>

<template>
  <div>
    <h1>Modals</h1>
    <button @click = "showModal = true" :class = "btnStyleDark">Show Modal</button>

    <Modal v-if = "showModal" @close = "showModal = false" :btn-style = "btnStyleDark">
      <template #title>My new title</template>
      <p>
        Lorem, ipsum dolor sit amet consectetur adipisicing elit. Vel tempora quibusdam tenetur,
        debitis autem fugit a nesciunt mollitia ipsa inventore nostrum perspiciatis neque dolor id
        magnam facere eum similique? Adipisci.
      </p>
    </Modal>
  </div>
</template>

Мой дочерний компонент

Модальный.vue

<script setup>
import { defineProps, defineEmits } from 'vue'

const props = defineProps({
  btnStyle: String,
})

const emit = defineEmits(['close'])
</script>

<template>
  <teleport to = "#modals-container">
    <div class = "modal z-10 absolute top-0 left-0 w-full h-full p-10 bg-yellow-50">
      <h1><slot name = "title" /></h1>
      <slot />
      <pre>{{ $slots.title() }}</pre>
      <button :class = "btnStyle" @click = "$emit('close')">Hide modal</button>
    </div>
  </teleport>
</template>

Ошибка в хроме:

TypeError: преобразование круговой структуры в JSON --> начиная с объекта с помощью конструктора Object | свойство 'vnode' -> объект с конструктором 'Object' --- свойство "компонент" замыкает круг в JSON.stringify() в toDisplayString (chunk-U6BEPC57.js?v=60065120:256:154)

Если я удалю () из <pre>{{ $slots.title() }}</pre> внутри дочернего элемента, я смогу увидеть это напечатанным в теге <pre> на странице без ошибки:

Однако эти данные мне ни о чем не говорят, а также не совпадают с данными, распечатанными из этого видеокурса:

Что я пробовал


Использование импорта useSlots

Это приводит к той же ошибке, но первый файл console.info работает!

<script setup>
import { defineProps, defineEmits, useSlots, onMounted } from 'vue'

const props = defineProps({
  btnStyle: String,
})

const emit = defineEmits(['close'])

const slots = useSlots()

console.info(slots.title())

onMounted(() => {
  console.info(slots)
})
</script>

<template>
  <teleport to = "#modals-container">
    <div class = "modal z-10 absolute top-0 left-0 w-full h-full p-10 bg-yellow-50">
      <h1><slot name = "title" /></h1>
      <slot />
      <pre>{{ $slots.title() }}</pre>
      <!-- <pre>{{ slots.title ? slots.title()[0] : '' }}</pre> -->

      <button :class = "btnStyle" @click = "$emit('close')">Hide modal</button>
    </div>
  </teleport>
</template>

Я также попробовал <pre>{{ slots.title() }}</pre> без $, но все равно выдает ошибку.

В вопросе отсутствует четкая формулировка проблемы. У вас есть цель, о которой вы не упомянули, или вы хотите отладить содержимое слота, или вам просто интересно, почему <pre> не работает?

Estus Flask 16.06.2024 19:35

Я обновлю вопрос, но в основном я хочу, чтобы то, что напечатано в console.info(slots.title()), весь объект внутри массива было распечатано в предварительной версии, а не эта нечитаемая функция.

Leon Gaban 17.06.2024 01:53
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
60
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Я использую const slots = useSlots();

<div v-for = "(value, key) in slots.title()[0]" :key = "key">
  <strong>{{ key.toString() }}:</strong>
  {{ value ? value.toString() : "null" }}
</div>`

На этапе тестирования я создал простую функцию:

<button @click = "close">Hide modal</button>

function close() {
  console.info(slots.title()[0]);
  emit("close");
}

И у меня получилось то, что вы показываете на скриншоте udemy.

Маленькая подсказка напоследок: я только что заметил в вашем коде, что в Vue3 вы объявляете событие генерации, поэтому вам нужно удалить '$' => @click = "emit('close')"

Ах, спасибо, да, это сработало, проверка каждого ключа на ноль... Интересно, возможно, наша разница в том, что я использую Typescript, а он нет, но странно. В любом случае спасибо! Я считаю маловероятным, что мне понадобится распечатывать данные о слотах на реальной странице, но полезно знать, как это обойти :)

Leon Gaban 17.06.2024 01:58

Другие вопросы по теме