javascript - How to set up Vue 3 parent component to emit event to child component - Stack Overflow

I am attempting to set up a button in a Vue 3 Tailwind parent ponent to trigger a HeadlessUI transition

I am attempting to set up a button in a Vue 3 Tailwind parent ponent to trigger a HeadlessUI transition event in a child ponent. My goal is to enable the button in the parent to emit an event, while the child ponent "watches" for the event before triggering the transition event as part of the callback function in the watch. So far, I have the parent ponent set up to trigger the emit, while the child ponent 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 ponent set up correctly, so as to watch for the button click in the parent ponent. How can I go about enabling the child ponent to watch for the click of the button in the parent ponent?

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 './ponents/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>

I am attempting to set up a button in a Vue 3 Tailwind parent ponent to trigger a HeadlessUI transition event in a child ponent. My goal is to enable the button in the parent to emit an event, while the child ponent "watches" for the event before triggering the transition event as part of the callback function in the watch. So far, I have the parent ponent set up to trigger the emit, while the child ponent 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 ponent set up correctly, so as to watch for the button click in the parent ponent. How can I go about enabling the child ponent to watch for the click of the button in the parent ponent?

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 './ponents/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>
Share Improve this question edited Apr 21, 2022 at 17:54 JS_is_awesome18 asked Apr 21, 2022 at 4:59 JS_is_awesome18JS_is_awesome18 1,7778 gold badges41 silver badges79 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 2

events should go up and state should go down.

make your child ponent 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./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

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 './ponents/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>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745177877a4615280.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信