You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3+Laravel9环境下Flowbite组件交互失效问题求助

Flowbite Vue组件交互失效排查(Vue3+Tailwind3+Laravel9)

问题现象

  • 手风琴组件无法打开/关闭,始终处于打开状态
  • 模态框无法关闭,轮播组件无法切换幻灯片

手风琴代码示例

<template>
  <div id="accordion-arrow-icon" data-accordion="open">
    <h2 id="accordion-arrow-icon-heading-1">
      <button type="button" class="flex items-center justify-between w-full p-5 font-medium text-left text-gray-900 bg-gray-100 border border-b-0 border-gray-200 rounded-t-xl focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-800 dark:border-gray-700 dark:text-white dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-800" data-accordion-target="#accordion-arrow-icon-body-1" aria-expanded="true" aria-controls="accordion-arrow-icon-body-1">
        <span>Accordion without an arrow</span>
      </button>
    </h2>
    <div id="accordion-arrow-icon-body-1" aria-labelledby="accordion-arrow-icon-heading-1">
      <div class="p-5 font-light border border-b-0 border-gray-200 dark:border-gray-700 dark:bg-gray-900">
        <p class="mb-2 text-gray-500 dark:text-gray-400">Flowbite is an open-source library of interactive components built on top of Tailwind CSS including buttons, dropdowns, modals, navbars, and more.</p>
        <p class="text-gray-500 dark:text-gray-400">Check out this guide to learn how to <a href="/docs/getting-started/introduction/" class="text-blue-600 dark:text-blue-500 hover:underline">get started</a> and start developing websites even faster with components on top of Tailwind CSS.</p>
      </div>
    </div>
    <h2 id="accordion-arrow-icon-heading-2">
      <button type="button" class="flex items-center justify-between w-full p-5 font-medium text-left text-gray-500 border border-b-0 border-gray-200 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-800 dark:border-gray-700 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800" data-accordion-target="#accordion-arrow-icon-body-2" aria-expanded="false" aria-controls="accordion-arrow-icon-body-2">
        <span>Accordion with another icon</span>
        <svg data-accordion-icon class="w-6 h-6 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 13l-3 3m0 0l-3-3m3 3V8m0 13a9 9 0 110-18 9 9 0 010 18z"></path></svg>
      </button>
    </h2>
    <div id="accordion-arrow-icon-body-2" class="hidden" aria-labelledby="accordion-arrow-icon-heading-2">
      <div class="p-5 font-light border border-b-0 border-gray-200 dark:border-gray-700">
        <p class="mb-2 text-gray-500 dark:text-gray-400">Flowbite is first conceptualized and designed using the Figma software so everything you see in the library has a design equivalent in our Figma file.</p>
        <p class="text-gray-500 dark:text-gray-400">Check out the <a href="https://flowbite.com/figma/" class="text-blue-600 dark:text-blue-500 hover:underline">Figma design system</a> based on the utility classes from Tailwind CSS and components from Flowbite.</p>
      </div>
    </div>
    <h2 id="accordion-arrow-icon-heading-3">
      <button type="button" class="flex items-center justify-between w-full p-5 font-medium text-left text-gray-500 border border-gray-200 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-800 dark:border-gray-700 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800" data-accordion-target="#accordion-arrow-icon-body-3" aria-expanded="false" aria-controls="accordion-arrow-icon-body-3">
        <span>Accordion without arrow rotation</span>
        <svg class="w-6 h-6 shrink-0" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
      </button>
    </h2>
    <div id="accordion-arrow-icon-body-3" class="hidden" aria-labelledby="accordion-arrow-icon-heading-3">
      <div class="p-5 font-light border border-t-0 border-gray-200 dark:border-gray-700">
        <p class="mb-2 text-gray-500 dark:text-gray-400">The main difference is that the core components from Flowbite are open source under the MIT license, whereas Tailwind UI is a paid product. Another difference is that Flowbite relies on smaller and standalone components, whereas Tailwind UI offers sections of pages.</p>
        <p class="mb-2 text-gray-500 dark:text-gray-400">However, we actually recommend using both Flowbite, Flowbite Pro, and even Tailwind UI as there is no technical reason stopping you from using the best of two worlds.</p>
        <p class="mb-2 text-gray-500 dark:text-gray-400">Learn more about these technologies:</p>
        <ul class="pl-5 text-gray-500 list-disc dark:text-gray-400">
          <li><a href="https://flowbite.com/pro/" class="text-blue-600 dark:text-blue-500 hover:underline">Flowbite Pro</a></li>
          <li><a href="https://tailwindui.com/" rel="nofollow" class="text-blue-600 dark:text-blue-500 hover:underline">Tailwind UI</a></li>
        </ul>
      </div>
    </div>
  </div>
</template>

原JavaScript代码

// create an array of objects with the id, trigger element (eg. button), and the content element
const accordionItems = [
    {
        id: 'accordion-example-heading-1',
        triggerEl: document.querySelector('#accordion-example-heading-1'),
        targetEl: document.querySelector('#accordion-example-body-1'),
        active: true
    },
    {
        id: 'accordion-example-heading-2',
        triggerEl: document.querySelector('#accordion-example-heading-2'),
        targetEl: document.querySelector('#accordion-example-body-2'),
        active: false
    },
    {
        id: 'accordion-example-heading-3',
        triggerEl: document.querySelector('#accordion-example-heading-3'),
        targetEl: document.querySelector('#accordion-example-body-3'),
        active: false
    }
];

// options with default values
const options = {
    alwaysOpen: true,
    activeClasses: 'bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white',
    inactiveClasses: 'text-gray-500 dark:text-gray-400',
    onOpen: (item) => {
        console.log('accordion item has been shown');
        console.log(item);
    },
    onClose: (item) => {
        console.log('accordion item has been hidden');
        console.log(item);
    },
    onToggle: (item) => {
        console.log('accordion item has been toggled');
        console.log(item);
    },
};

核心问题与修复方案

1. 修正ID匹配错误

原JS代码中的ID与模板中的ID完全不匹配(模板用accordion-arrow-icon-*,JS用accordion-example-*),导致无法找到目标DOM元素。修正后的JS数组:

const accordionItems = [
    {
        id: 'accordion-arrow-icon-heading-1',
        triggerEl: document.querySelector('#accordion-arrow-icon-heading-1 button'),
        targetEl: document.querySelector('#accordion-arrow-icon-body-1'),
        active: true
    },
    {
        id: 'accordion-arrow-icon-heading-2',
        triggerEl: document.querySelector('#accordion-arrow-icon-heading-2 button'),
        targetEl: document.querySelector('#accordion-arrow-icon-body-2'),
        active: false
    },
    {
        id: 'accordion-arrow-icon-heading-3',
        triggerEl: document.querySelector('#accordion-arrow-icon-heading-3 button'),
        targetEl: document.querySelector('#accordion-arrow-icon-body-3'),
        active: false
    }
];

2. 在Vue生命周期钩子中初始化组件

Vue组件DOM在mounted阶段才完全渲染完成,必须将初始化代码放在mounted中,确保能获取到DOM元素:

<template>
  <!-- 手风琴模板代码 -->
</template>

<script setup>
import { onMounted } from 'vue';
import { Accordion } from 'flowbite';

onMounted(() => {
  // 修正后的accordionItems数组
  const accordionItems = [
    {
        id: 'accordion-arrow-icon-heading-1',
        triggerEl: document.querySelector('#accordion-arrow-icon-heading-1 button'),
        targetEl: document.querySelector('#accordion-arrow-icon-body-1'),
        active: true
    },
    {
        id: 'accordion-arrow-icon-heading-2',
        triggerEl: document.querySelector('#accordion-arrow-icon-heading-2 button'),
        targetEl: document.querySelector('#accordion-arrow-icon-body-2'),
        active: false
    },
    {
        id: 'accordion-arrow-icon-heading-3',
        triggerEl: document.querySelector('#accordion-arrow-icon-heading-3 button'),
        targetEl: document.querySelector('#accordion-arrow-icon-body-3'),
        active: false
    }
  ];

  const options = {
      alwaysOpen: true,
      activeClasses: 'bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white',
      inactiveClasses: 'text-gray-500 dark:text-gray-400',
      onOpen: (item) => {
          console.log('accordion item has been shown');
          console.log(item);
      },
      onClose: (item) => {
          console.log('accordion item has been hidden');
          console.log(item);
      },
      onToggle: (item) => {
          console.log('accordion item has been toggled');
          console.log(item);
      },
  };

  // 初始化手风琴
  new Accordion(accordionItems, options);
});
</script>

3. 优先使用Flowbite Vue组件(更简洁)

如果安装的是Flowbite Vue组件库,直接使用封装好的Vue组件可自动绑定交互:

<template>
  <Accordion>
    <AccordionPanel>
      <AccordionHeader>Accordion without an arrow</AccordionHeader>
      <AccordionBody>
        <p class="mb-2 text-gray-500 dark:text-gray-400">
          Flowbite是基于Tailwind CSS构建的开源交互组件库,包含按钮、下拉菜单、模态框、导航栏等。
        </p>
        <p class="text-gray-500 dark:text-gray-400">
          查看指南了解如何快速开始,基于Tailwind CSS组件更快开发网站。
        </p>
      </AccordionBody>
    </AccordionPanel>
    <!-- 其他面板重复上述结构 -->
  </Accordion>
</template>

<script setup>
import { Accordion, AccordionPanel, AccordionHeader, AccordionBody } from '@flowbite/vue';
</script>

4. 全局初始化Flowbite(可选)

若项目中有大量Flowbite组件,可在main.js中全局注册:

import { createApp } from 'vue';
import App from './App.vue';
import Flowbite from 'flowbite';

const app = createApp(App);
app.use(Flowbite);
app.mount('#app');

内容的提问来源于stack exchange,提问作者Sham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 17:24:18