如何设置VUE 3父组件以将事件发射到儿童组件

发布于 2025-01-22 23:45:44 字数 2799 浏览 1 评论 0原文

我正在尝试在VUE 3尾风父组件中设置一个按钮,以触发儿童组件中的Headlesseui过渡事件。我的目标是启用父母中的按钮发出事件,而孩子组件则在触发过渡事件之前“手表”作为手表回调功能的一部分。到目前为止,我已经设置了父组件来触发EMIT,而设置了子组件以观察“过渡”事件。但是,该事件没有被执行。恐怕我没有正确设置的子组件中的手表,以便观察父部件中的按钮。如何使孩子组件能够查看父组件中的按钮的单击?

这是我到目前为止的代码:

父母:

<!-- This example requires Tailwind CSS v2.0+ -->
<template>
  <div class="min-h-full">
    <Disclosure as="nav" class="bg-gray-800">
      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
        <div class="flex items-center justify-between h-16">
          <div class="flex items-center">
            <div class="hidden md:block">
              <div class="ml-10 flex items-baseline space-x-4">
                <button type="button" @click="transition" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">Click to transition</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </Disclosure>

    <main>
      <div class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
        <div class="px-4 py-6 sm:px-0">
          <HelloWorld :event="transition" />
        </div>
      </div>
    </main>
  </div>
</template>

<script setup>
import { Disclosure, DisclosureButton, DisclosurePanel, Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'
import { BellIcon, MenuIcon, XIcon } from '@heroicons/vue/outline'
import HelloWorld from './components/HelloWorld.vue'
</script>

孩子:

<template>
  <div class="flex flex-col items-center py-16">
    <div class="w-96 h-96">
      <TransitionRoot
        appear
        :show="isShowing"
        as="template"
        enter="transform transition duration-[400ms]"
        enter-from="opacity-0 rotate-[-120deg] scale-50"
        enter-to="opacity-100 rotate-0 scale-100"
        leave="transform duration-200 transition ease-in-out"
        leave-from="opacity-100 rotate-0 scale-100 "
        leave-to="opacity-0 scale-95 "
      >
        <div class="w-full h-full bg-gray-400 rounded-md shadow-lg" />
      </TransitionRoot>
    </div>
  </div>
</template>

<script setup>
import { ref, toRefs, watch } from 'vue'
import { TransitionRoot } from '@headlessui/vue'

const props = defineProps({
  transition: Function
})
const { transition } = toRefs(props)
const isShowing = ref(true)

watch(transition, () => {
  isShowing.value = false

  setTimeout(() => {
    isShowing.value = true
  }, 500)
})
</script>

I am attempting to set up a button in a Vue 3 Tailwind parent component to trigger a HeadlessUI transition event in a child component. My goal is to enable the button in the parent to emit an event, while the child component "watches" for the event before triggering the transition event as part of the callback function in the watch. So far, I have the parent component set up to trigger the emit, while the child component is set up to watch for the "transition" event. However, the event is not being executed. I'm afraid I don't have the watch in the child component set up correctly, so as to watch for the button click in the parent component. How can I go about enabling the child component to watch for the click of the button in the parent component?

Here is my code so far:

Parent:

<!-- This example requires Tailwind CSS v2.0+ -->
<template>
  <div class="min-h-full">
    <Disclosure as="nav" class="bg-gray-800">
      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
        <div class="flex items-center justify-between h-16">
          <div class="flex items-center">
            <div class="hidden md:block">
              <div class="ml-10 flex items-baseline space-x-4">
                <button type="button" @click="transition" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">Click to transition</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </Disclosure>

    <main>
      <div class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
        <div class="px-4 py-6 sm:px-0">
          <HelloWorld :event="transition" />
        </div>
      </div>
    </main>
  </div>
</template>

<script setup>
import { Disclosure, DisclosureButton, DisclosurePanel, Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'
import { BellIcon, MenuIcon, XIcon } from '@heroicons/vue/outline'
import HelloWorld from './components/HelloWorld.vue'
</script>

Child:

<template>
  <div class="flex flex-col items-center py-16">
    <div class="w-96 h-96">
      <TransitionRoot
        appear
        :show="isShowing"
        as="template"
        enter="transform transition duration-[400ms]"
        enter-from="opacity-0 rotate-[-120deg] scale-50"
        enter-to="opacity-100 rotate-0 scale-100"
        leave="transform duration-200 transition ease-in-out"
        leave-from="opacity-100 rotate-0 scale-100 "
        leave-to="opacity-0 scale-95 "
      >
        <div class="w-full h-full bg-gray-400 rounded-md shadow-lg" />
      </TransitionRoot>
    </div>
  </div>
</template>

<script setup>
import { ref, toRefs, watch } from 'vue'
import { TransitionRoot } from '@headlessui/vue'

const props = defineProps({
  transition: Function
})
const { transition } = toRefs(props)
const isShowing = ref(true)

watch(transition, () => {
  isShowing.value = false

  setTimeout(() => {
    isShowing.value = true
  }, 500)
})
</script>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

萌能量女王 2025-01-29 23:45:44

事件应该上升,状态应下降。

使您的孩子组件观看属性,父母中的按钮应更改该属性更新的状态

const {transition} = torefs(props)

您可能会在此处失去反应性。

https://stackoverflow.com/a/64926664/420096

update2:

更多信息 但是直接指向道具也很好:
https://codesandbox.io/s/relaxed-sea/relaxed-sea -y95x6c?file =/src/app.vue

events should go up and state should go down.

make your child component to watch a property and the button in parent should change the state of that property

update:

const { transition } = toRefs(props)

you might be losing reactivity here.

more info: https://stackoverflow.com/a/64926664/420096

update2:

the way you made it should work, but point directly to the prop is fine too:
https://codesandbox.io/s/relaxed-sea-y95x6c?file=/src/App.vue

傻比既视感 2025-01-29 23:45:44

根据Sombriks的反馈,这是答案:

父母:

<!-- This example requires Tailwind CSS v2.0+ -->
<template>
  <div class="min-h-full">
    <Disclosure as="nav" class="bg-gray-800">
      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
        <div class="flex items-center justify-between h-16">
          <div class="flex items-center">
            <div class="hidden md:block">
              <div class="ml-10 flex items-baseline space-x-4">
                <button type="button" @click="transition" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">Click to transition</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </Disclosure>

    <main>
      <div class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
        <div class="px-4 py-6 sm:px-0">
          <HelloWorld :show="show" />
        </div>
      </div>
    </main>
  </div>
</template>

<script setup>
import { Disclosure, DisclosureButton, DisclosurePanel, Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'
import { BellIcon, MenuIcon, XIcon } from '@heroicons/vue/outline'
import { ref } from 'vue'
import HelloWorld from './components/HelloWorld.vue'

const show = ref(true)

const transition = () => {
  show.value = !show.value
}

</script>

孩子:

<template>
  <div class="flex flex-col items-center py-16">
    <div class="w-96 h-96">
      <TransitionRoot
        appear
        :show="isShowing"
        as="template"
        enter="transform transition duration-[400ms]"
        enter-from="opacity-0 rotate-[-120deg] scale-50"
        enter-to="opacity-100 rotate-0 scale-100"
        leave="transform duration-200 transition ease-in-out"
        leave-from="opacity-100 rotate-0 scale-100 "
        leave-to="opacity-0 scale-95 "
      >
        <div class="w-full h-full bg-gray-400 rounded-md shadow-lg" />
      </TransitionRoot>
    </div>
  </div>
</template>

<script setup>
import { ref, toRefs, watch } from 'vue'
import { TransitionRoot } from '@headlessui/vue'

const props = defineProps({
  show: Boolean
})
const { show } = toRefs(props)
const isShowing = ref(true)

watch(show, () => {
  isShowing.value = false

  setTimeout(() => {
    isShowing.value = true
  }, 500)
})
</script>

Based on Sombriks' feedback, here is the answer:

Parent:

<!-- This example requires Tailwind CSS v2.0+ -->
<template>
  <div class="min-h-full">
    <Disclosure as="nav" class="bg-gray-800">
      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
        <div class="flex items-center justify-between h-16">
          <div class="flex items-center">
            <div class="hidden md:block">
              <div class="ml-10 flex items-baseline space-x-4">
                <button type="button" @click="transition" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">Click to transition</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </Disclosure>

    <main>
      <div class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
        <div class="px-4 py-6 sm:px-0">
          <HelloWorld :show="show" />
        </div>
      </div>
    </main>
  </div>
</template>

<script setup>
import { Disclosure, DisclosureButton, DisclosurePanel, Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'
import { BellIcon, MenuIcon, XIcon } from '@heroicons/vue/outline'
import { ref } from 'vue'
import HelloWorld from './components/HelloWorld.vue'

const show = ref(true)

const transition = () => {
  show.value = !show.value
}

</script>

Child:

<template>
  <div class="flex flex-col items-center py-16">
    <div class="w-96 h-96">
      <TransitionRoot
        appear
        :show="isShowing"
        as="template"
        enter="transform transition duration-[400ms]"
        enter-from="opacity-0 rotate-[-120deg] scale-50"
        enter-to="opacity-100 rotate-0 scale-100"
        leave="transform duration-200 transition ease-in-out"
        leave-from="opacity-100 rotate-0 scale-100 "
        leave-to="opacity-0 scale-95 "
      >
        <div class="w-full h-full bg-gray-400 rounded-md shadow-lg" />
      </TransitionRoot>
    </div>
  </div>
</template>

<script setup>
import { ref, toRefs, watch } from 'vue'
import { TransitionRoot } from '@headlessui/vue'

const props = defineProps({
  show: Boolean
})
const { show } = toRefs(props)
const isShowing = ref(true)

watch(show, () => {
  isShowing.value = false

  setTimeout(() => {
    isShowing.value = true
  }, 500)
})
</script>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文