当前位置:首页 > VUE

vue实现一个标签选择

2026-01-07 06:44:49VUE

Vue 标签选择组件实现

基础实现

使用 Vue 的 v-for 和 v-model 指令可以快速实现标签选择功能:

<template>
  <div class="tag-selector">
    <div 
      v-for="tag in availableTags" 
      :key="tag"
      class="tag"
      :class="{ 'selected': selectedTags.includes(tag) }"
      @click="toggleTag(tag)"
    >
      {{ tag }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      availableTags: ['前端', '后端', '移动端', '数据库', '运维'],
      selectedTags: []
    }
  },
  methods: {
    toggleTag(tag) {
      const index = this.selectedTags.indexOf(tag)
      if (index === -1) {
        this.selectedTags.push(tag)
      } else {
        this.selectedTags.splice(index, 1)
      }
    }
  }
}
</script>

<style>
.tag-selector {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.tag {
  padding: 4px 12px;
  border: 1px solid #ddd;
  border-radius: 16px;
  cursor: pointer;
}
.tag.selected {
  background-color: #42b983;
  color: white;
  border-color: #42b983;
}
</style>

可编辑标签实现

实现允许用户添加新标签的功能:

<template>
  <div>
    <input 
      v-model="newTag"
      @keyup.enter="addTag"
      placeholder="输入新标签"
    />
    <button @click="addTag">添加</button>

    <div class="tag-container">
      <span 
        v-for="tag in tags"
        :key="tag"
        class="tag"
        @click="removeTag(tag)"
      >
        {{ tag }} ×
      </span>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tags: ['Vue', 'React', 'Angular'],
      newTag: ''
    }
  },
  methods: {
    addTag() {
      if (this.newTag.trim() && !this.tags.includes(this.newTag)) {
        this.tags.push(this.newTag)
        this.newTag = ''
      }
    },
    removeTag(tag) {
      this.tags = this.tags.filter(t => t !== tag)
    }
  }
}
</script>

带搜索的标签选择器

结合输入搜索功能:

<template>
  <div>
    <input 
      v-model="searchQuery"
      placeholder="搜索标签..."
    />

    <div v-if="filteredTags.length">
      <div 
        v-for="tag in filteredTags"
        :key="tag"
        class="tag-item"
        @click="selectTag(tag)"
      >
        {{ tag }}
      </div>
    </div>
    <div v-else>
      没有匹配的标签
    </div>

    <div class="selected-tags">
      已选择: {{ selectedTags.join(', ') }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      allTags: ['JavaScript', 'TypeScript', 'HTML', 'CSS', 'Node.js'],
      selectedTags: [],
      searchQuery: ''
    }
  },
  computed: {
    filteredTags() {
      return this.allTags.filter(tag => 
        tag.toLowerCase().includes(this.searchQuery.toLowerCase()) &&
        !this.selectedTags.includes(tag)
      )
    }
  },
  methods: {
    selectTag(tag) {
      this.selectedTags.push(tag)
      this.searchQuery = ''
    }
  }
}
</script>

组件封装

将标签选择器封装为可复用组件:

<!-- TagSelector.vue -->
<template>
  <div class="tag-selector">
    <div class="selected-tags">
      <span 
        v-for="tag in modelValue"
        :key="tag"
        class="tag"
        @click="removeTag(tag)"
      >
        {{ tag }} ×
      </span>
    </div>

    <input
      v-model="searchQuery"
      @keydown.enter="addNewTag"
      placeholder="添加标签..."
    />

    <div v-if="filteredTags.length" class="tag-options">
      <div
        v-for="tag in filteredTags"
        :key="tag"
        class="tag-option"
        @click="selectTag(tag)"
      >
        {{ tag }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    modelValue: {
      type: Array,
      required: true
    },
    availableTags: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      searchQuery: ''
    }
  },
  computed: {
    filteredTags() {
      return this.availableTags.filter(tag =>
        tag.toLowerCase().includes(this.searchQuery.toLowerCase()) &&
        !this.modelValue.includes(tag)
      )
    }
  },
  methods: {
    selectTag(tag) {
      this.$emit('update:modelValue', [...this.modelValue, tag])
      this.searchQuery = ''
    },
    removeTag(tag) {
      this.$emit('update:modelValue', this.modelValue.filter(t => t !== tag))
    },
    addNewTag() {
      if (this.searchQuery.trim() && !this.modelValue.includes(this.searchQuery)) {
        this.$emit('update:modelValue', [...this.modelValue, this.searchQuery])
        this.searchQuery = ''
      }
    }
  }
}
</script>

使用封装的组件:

<template>
  <TagSelector
    v-model="selectedTags"
    :available-tags="allTags"
  />
</template>

<script>
import TagSelector from './TagSelector.vue'

export default {
  components: { TagSelector },
  data() {
    return {
      allTags: ['Vue', 'React', 'Angular', 'Svelte'],
      selectedTags: []
    }
  }
}
</script>

第三方库方案

使用 vue-tags-input 等现成库:

npm install @voerro/vue-tagsinput
<template>
  <tags-input
    v-model="tags"
    :existing-tags="availableTags"
    :typeahead="true"
    placeholder="添加标签"
  />
</template>

<script>
import VoerroTagsInput from '@voerro/vue-tagsinput'

export default {
  components: {
    'tags-input': VoerroTagsInput
  },
  data() {
    return {
      tags: [],
      availableTags: [
        { key: 'vue', value: 'Vue.js' },
        { key: 'react', value: 'React' }
      ]
    }
  }
}
</script>

这些实现方案覆盖了从基础到高级的标签选择功能,可以根据项目需求选择合适的实现方式。

vue实现一个标签选择

标签: 标签vue
分享给朋友:

相关文章

vue的动画实现

vue的动画实现

Vue 动画实现方式 Vue 提供了多种方式实现动画效果,主要通过内置组件和第三方库支持。 使用 Vue 内置过渡组件 Vue 的 transition 和 transition-group 组件…

vue前端实现登录

vue前端实现登录

实现登录功能的基本流程 使用Vue实现登录功能需要结合前端框架和后端API交互。以下是一个典型的实现方案: 安装必要依赖 确保项目已安装axios用于HTTP请求: npm install axi…

vue实现无线滚动列表

vue实现无线滚动列表

无限滚动列表的实现方法 在Vue中实现无限滚动列表通常结合监听滚动事件和动态加载数据。以下是几种常见方法: 使用自定义指令 创建自定义指令v-infinite-scroll监听滚动事件:…

vue实现弹窗可切换

vue实现弹窗可切换

实现弹窗可切换的 Vue 方案 动态组件切换 通过 Vue 的 <component :is="currentComponent"> 动态加载不同弹窗组件,结合 v-if 控制显示状态。…

vue实现多选题

vue实现多选题

Vue实现多选题的方法 使用Vue实现多选题功能,可以通过v-model绑定数组、动态渲染选项、以及处理选中状态来实现。以下是一个完整的实现示例: 基础实现代码 <template>…

vue实现自定义登录

vue实现自定义登录

实现自定义登录的基本步骤 在Vue中实现自定义登录功能通常需要结合前端和后端技术。以下是一个基本的实现流程: 创建登录表单组件 使用Vue的单文件组件创建一个登录表单,包含用户名和密码输入框以及提…