当前位置:首页 > 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>

可编辑标签实现

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

vue实现一个标签选择

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

组件封装

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

vue实现一个标签选择

<!-- 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 实现语音功能的方法 使用 Web Speech API Vue 可以结合 Web Speech API 实现语音识别和合成功能。Web Speech API 包含 SpeechRecognit…

vue实现路径

vue实现路径

Vue 实现路径的方法 在 Vue 中实现路径管理通常涉及 Vue Router 的使用,以下是一些常见的实现方法: 安装 Vue Router 通过 npm 或 yarn 安装 Vue Route…

vue实现文章滚动

vue实现文章滚动

Vue 实现文章滚动效果 使用 CSS 实现基础滚动 通过 CSS 的 overflow 和 height 属性控制滚动区域,适用于静态内容滚动。在 Vue 模板中定义固定高度的容器,内容超出后自动滚…

vue router实现分页

vue router实现分页

Vue Router 实现分页的方法 在 Vue.js 中,可以通过 Vue Router 实现分页功能,通常需要结合路由参数和动态路由匹配。以下是几种常见的实现方式: 使用查询参数实现分页 在路由…

vue滚动插件实现

vue滚动插件实现

Vue 滚动插件实现方法 使用现有插件(推荐) 对于大多数场景,推荐使用成熟的 Vue 滚动插件,例如 vue-infinite-loading 或 vue-virtual-scroller。这些插件…

vue实现开关灯

vue实现开关灯

Vue实现开关灯效果 使用Vue实现开关灯效果可以通过数据绑定和条件渲染完成。以下是具体实现方式: 创建Vue实例并定义数据 new Vue({ el: '#app', data: {…