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

如何在Vue.js中创建动态表单/筛选项?附功能命名咨询

专业名称

这个功能在前端开发里通常被称为 多选标签选择器(Multi-select Tag Picker),也常被叫做可搜索多选下拉组件,是表单交互中很常见的筛选/选择类组件。

Vue.js 实现示例(Vue 3 Composition API)

以下是适合新手的基础实现,包含核心功能:搜索过滤、选中项添加/移除、已选项排除在下拉列表外。

模板部分

<template>
  <div class="tag-picker-container">
    <!-- 搜索输入框 -->
    <input 
      v-model="searchQuery"
      type="text"
      placeholder="输入项名称搜索..."
      class="search-input"
    />

    <!-- 过滤后的下拉选项列表 -->
    <ul v-if="filteredOptions.length > 0" class="options-list">
      <li 
        v-for="option in filteredOptions" 
        :key="option.id"
        @click="selectOption(option)"
        class="option-item"
      >
        {{ option.name }}
      </li>
    </ul>

    <!-- 已选中的标签区域 -->
    <div class="selected-tags">
      <span 
        v-for="tag in selectedTags" 
        :key="tag.id"
        class="tag-item"
      >
        {{ tag.name }}
        <button @click="removeTag(tag)" class="remove-btn">×</button>
      </span>
    </div>

    <!-- 用于提交的隐藏表单(和后端交互用) -->
    <form @submit.prevent="handleSubmit">
      <input type="hidden" :value="selectedTags.map(t => t.id).join(',')" name="selectedIds">
      <button type="submit" class="submit-btn">提交筛选</button>
    </form>
  </div>
</template>

脚本部分

<script setup>
import { ref, computed } from 'vue'

// 模拟从后端获取的全量选项数据(实际项目中可通过axios/fetch请求)
const allOptions = ref([
  { id: 1, name: '产品A' },
  { id: 2, name: '产品B' },
  { id: 3, name: '产品C' },
  { id: 4, name: '产品D' },
  { id: 5, name: '产品E' }
])

// 搜索关键词
const searchQuery = ref('')
// 已选中的标签数组
const selectedTags = ref([])

// 计算属性:过滤出可选的选项(排除已选中项,同时匹配搜索关键词)
const filteredOptions = computed(() => {
  const selectedIds = selectedTags.value.map(tag => tag.id)
  return allOptions.value.filter(option => {
    return !selectedIds.includes(option.id) && 
           option.name.toLowerCase().includes(searchQuery.value.toLowerCase())
  })
})

// 选中选项的方法
const selectOption = (option) => {
  selectedTags.value.push(option)
  searchQuery.value = '' // 选中后清空搜索框
}

// 移除已选标签的方法
const removeTag = (tag) => {
  const index = selectedTags.value.findIndex(t => t.id === tag.id)
  if (index !== -1) {
    selectedTags.value.splice(index, 1)
  }
}

// 表单提交处理(与后端交互的逻辑)
const handleSubmit = () => {
  // 这里可将selectedTags的ID数组传给后端,比如用axios发送POST请求
  console.log('提交的选中项ID:', selectedTags.value.map(t => t.id))
  // 示例:axios.post('/api/filter', { selectedIds: selectedTags.value.map(t => t.id) })
}
</script>

基础样式部分

<style scoped>
.tag-picker-container {
  max-width: 400px;
  margin: 20px;
}

.search-input {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 14px;
}

.options-list {
  list-style: none;
  padding: 0;
  margin: 8px 0;
  border: 1px solid #ddd;
  border-radius: 4px;
  max-height: 200px;
  overflow-y: auto;
}

.option-item {
  padding: 8px 12px;
  cursor: pointer;
}

.option-item:hover {
  background-color: #f5f5f5;
}

.selected-tags {
  margin: 12px 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.tag-item {
  background-color: #e0f2fe;
  padding: 4px 8px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 14px;
}

.remove-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: #666;
  font-size: 16px;
  line-height: 1;
}

.submit-btn {
  padding: 8px 16px;
  background-color: #3b82f6;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
</style>
关键逻辑说明
  • 搜索过滤:通过computed计算属性实时筛选选项,同时排除已选中的项
  • 选中/移除:选中时将选项加入selectedTags数组,移除时从数组中删除,保证下拉列表不会重复显示已选项
  • 表单交互:提交时可将已选项的ID数组传给后端,用于数据筛选或详情查询

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 09:55:22