如何设置 Vue 3 parent 组件以向 child 组件发出事件

How to set up Vue 3 parent component to emit event to child component

我正在尝试在 Vue 3 Tailwind parent 组件中设置一个按钮,以触发 child 组件中的 HeadlessUI 转换事件。我的目标是使 parent 中的按钮能够发出事件,而 child 组件在触发转换事件之前“监视”事件,作为监视中回调函数的一部分。到目前为止,我已将 parent 组件设置为触发发射,而将 child 组件设置为监视“转换”事件。但是,该事件未被执行。恐怕我没有正确设置 child 组件中的监视,以便监视 parent 组件中的按钮点击。我怎样才能启用 child 组件来监视 parent 组件中按钮的点击?

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

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>

你想从父子之间传递一些东西吗?这个概念错了!你只需使用道具将 s.th 从父级传递给子级,并使用 emit

从子级将 s.th 传递给父级

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

让你的子组件观看 属性 并且父组件中的按钮应该改变那个 属性

的状态

更新:

const { transition } = toRefs(props)

你可能会失去反应。

更多信息:

更新2:

您制作它的方式应该可行,但直接指向道具也可以: https://codesandbox.io/s/relaxed-sea-y95x6c?file=/src/App.vue

根据 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>