[英]How to set up Vue 3 parent component to emit event to child component
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.我试图在 Vue 3 Tailwind 父组件中设置一个按钮来触发子组件中的 HeadlessUI 转换事件。 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.我的目标是使父组件中的按钮能够发出事件,而子组件在触发转换事件之前“监视”该事件,作为手表中回调 function 的一部分。 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? go 如何让子组件监听父组件中按钮的点击?
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>
events should go up and state should go down.事件应该 go 向上和 state 应该 go 向下。
make your child component to watch a property and the button in parent should change the state of that property让您的子组件观看属性,父组件中的按钮应更改该属性的 state
update:更新:
const { transition } = toRefs(props)
you might be losing reactivity here.您可能会在这里失去反应性。
more info: https://stackoverflow.com/a/64926664/420096更多信息: https://stackoverflow.com/a/64926664/420096
update2:更新2:
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你制作它的方式应该有效,但直接指向道具也很好: https://codesandbox.io/s/relaxed-sea-y95x6c?file=/src/App.vue
Based on Sombriks' feedback, here is the answer:根据 Sombriks 的反馈,答案如下:
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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.