首先,需要在项目中引入 @hotwired/stimulus 和 tailwindcss。然后,可以创建一个 Stimulus 控制器来实现多层级 Cascader 级联选择器的功能。

以下是一个示例控制器代码:

import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
  static targets = ['menu', 'option']

  connect() {
    // 初始化菜单
    this.openMenu(0)
  }

  // 点击选项时触发
  selectOption(event) {
    const option = event.currentTarget
    const level = parseInt(option.dataset.level)

    // 更新选项
    this.updateOption(level, option.textContent)

    // 关闭之前的菜单
    this.closeMenu(level)

    // 打开下一个菜单
    this.openMenu(level + 1)
  }

  // 打开菜单
  openMenu(level) {
    const menu = this.menuTargets[level]

    if (menu) {
      menu.classList.remove('hidden')
      menu.classList.add('block')
    }
  }

  // 关闭菜单
  closeMenu(level) {
    const menu = this.menuTargets[level]

    if (menu) {
      menu.classList.remove('block')
      menu.classList.add('hidden')
    }
  }

  // 更新选项
  updateOption(level, value) {
    const option = this.optionTargets[level]
    option.textContent = value
  }
}

在 HTML 中,可以使用以下代码来定义级联选择器:

<div data-controller="cascader">
  <div class="relative">
    <button type="button" class="inline-flex justify-between items-center w-full px-4 py-2 border border-gray-300 bg-white text-gray-700 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" data-action="click->cascader#openMenu">
      <span class="block truncate" data-target="cascader.option"></span>
      <svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
        <path fill-rule="evenodd" d="M10.707 3.293a1 1 0 00-1.414 0l-6 6a1 1 0 001.414 1.414L4 7.414V17a1 1 0 001 1h10a1 1 0 001-1V7.414l1.293 1.293a1 1 0 001.414-1.414l-6-6z" clip-rule="evenodd" />
      </svg>
    </button>
    <div class="absolute z-10 right-0 mt-2 w-64 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 hidden" data-target="cascader.menu">
      <ul class="py-1">
        <li><a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900" data-action="click->cascader#selectOption" data-level="0">Option 1</a></li>
        <li><a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900" data-action="click->cascader#selectOption" data-level="0">Option 2</a></li>
      </ul>
    </div>
  </div>
  <div class="relative">
    <button type="button" class="inline-flex justify-between items-center w-full px-4 py-2 border border-gray-300 bg-white text-gray-700 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" data-action="click->cascader#openMenu">
      <span class="block truncate" data-target="cascader.option"></span>
      <svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
        <path fill-rule="evenodd" d="M10.707 3.293a1 1 0 00-1.414 0l-6 6a1 1 0 001.414 1.414L4 7.414V17a1 1 0 001 1h10a1 1 0 001-1V7.414l1.293 1.293a1 1 0 001.414-1.414l-6-6z" clip-rule="evenodd" />
      </svg>
    </button>
    <div class="absolute z-10 right-0 mt-2 w-64 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 hidden" data-target="cascader.menu">
      <ul class="py-1">
        <li><a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900" data-action="click->cascader#selectOption" data-level="1">Option 1-1</a></li>
        <li><a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900" data-action="click->cascader#selectOption" data-level="1">Option 1-2</a></li>
      </ul>
    </div>
  </div>
  <div class="relative">
    <button type="button" class="inline-flex justify-between items-center w-full px-4 py-2 border border-gray-300 bg-white text-gray-700 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" data-action="click->cascader#openMenu">
      <span class="block truncate" data-target="cascader.option"></span>
      <svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
        <path fill-rule="evenodd" d="M10.707 3.293a1 1 0 00-1.414 0l-6 6a1 1 0 001.414 1.414L4 7.414V17a1 1 0 001 1h10a1 1 0 001-1V7.414l1.293 1.293a1 1 0 001.414-1.414l-6-6z" clip-rule="evenodd" />
      </svg>
    </button>
    <div class="absolute z-10 right-0 mt-2 w-64 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 hidden" data-target="cascader.menu">
      <ul class="py-1">
        <li><a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900" data-action="click->cascader#selectOption" data-level="2">Option 1-1-1</a></li>
        <li><a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900" data-action="click->cascader#selectOption" data-level="2">Option 1-1-2</a></li>
      </ul>
    </div>
  </div>
</div>

在这个示例中,我们定义了三个按钮,每个按钮都有一个菜单,用于显示级联选择器的选项。每个菜单都有一个 data-level 属性,用于指示该菜单属于级联选择器的哪个级别。

我们还定义了一个名为 cascader 的 Stimulus 控制器,并在按钮和菜单上使用了 data-controller 和 data-target 属性来将它们与控制器绑定起来。控制器中的 selectOption 方法负责更新选项并打开下一个菜单,openMenu 和 closeMenu 方法用于打开和关闭菜单,updateOption 方法用于更新选项的文本内容。

最后,在 CSS 中,我们使用 tailwindcss 来样式化级联选择器的外观和交互效果。

这样,我们就可以使用 @hotwired/stimulus 和 tailwindcss 来实现像 element-plus 多层级 Cascader 级联选择器的功能了。


原文地址: https://www.cveoy.top/t/topic/FwR 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录