需要实现既可以选择,也可以手动输入作为新标签的功能,且手动输入的新标签区别展示。

(ps:尝试用iView的Select控件,将allow-create=true后基本能实现,只是在无下拉项数据时,会出现选不中的情况,所以自己学习研究了一下)

效果图是这样的:

采用的组件vue-treeselect, 是一个多选组件,功能强大界面美观,支持模糊匹配异步加载等,方便封装。具体介绍和用法参见官:https://www.vue-treeselect.cn/

需要采用异步搜索模式来加载,设置

  • async --设置为异步搜索模式
  • load-options --异步搜索事件,用于将结果数据回传到组件中
  • default-options --异步搜索模式中,初始化进入组件时,默认加载搜索字符串为空的搜索条件(如果不设置会出现刚进组件没有输入查询字符串时,下拉选项里无数据)

另外需要修改

  • clear-on-select --在选择下拉项后,清空编辑框中的搜索字符串

  • select  --在选择下拉选项后clear-on-select不能清空搜索字符串,手动在选择事件后清空

贴一下代码:

<!--组件部分 (vue文件)-->
<template>
    <TreeSelect
      ref="tagSelectRef"
      v-model="valueSelf"
      placeholder="请输入或选择标签"
      multiple
      async
      :default-options="true"
      :load-options="loadTagsOptions"     
      :clear-on-select="clearOnSelect"
      @select="selectItem">
      <label slot="option-label" slot-scope="{ node }">
        <b v-if="node.isNew">{{ node.label }}{{'  (新标签)'}}</b>
        <span v-else>{{ node.label }}</span>
      </label>
    </TreeSelect>
</template>

<script>
import TreeSelect, { ASYNC_SEARCH } from "@riophae/vue-treeselect"
import '@riophae/vue-treeselect/dist/vue-treeselect.css'

export default {
  name: 'tag-select',
  components:{
    TreeSelect
  },
  model:{
    prop: 'value',
    event: 'change'
  },
  props: {
    //选择的数据项
    value:{
      type: Array,
      default: []
    },
    //已有的数据项
    allTags:{
      type: Array,
      default: []
    },
    // 选择后是否清除搜索文字
    clearOnSelect:{
      type: Boolean,
      default: true
    },
    // 新标签是否区别颜色
    isNewTagDifference:{
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      valueSelf: this.value,   //自身展示的value
    }
  },
  watch:{
    valueSelf(newValue, oldVaule){
      if(newValue !== this.value){
        this.$emit('change', newValue)
      }
    }
  },
  methods:{
    //异步加载标签
    loadTagsOptions({ action, searchQuery, callback }){
      //输入时异步加载
      if(action === ASYNC_SEARCH){
        let options = []
        // 1. 搜索空字符串,则展示全部已有标签
        if(searchQuery.trim()===""){
          this.allTags.forEach(x=>{
            options.push({
              id: x,
              label: x
            })
          })
        }
        //2. 不为空,则生成新标签 + 过滤已有标签
        else{
          //2.1 过滤已有标签
          this.allTags.forEach(x=>{
            if(x.indexOf(searchQuery) > -1){
              options.push({
                id: x,
                label: x,
              })
            }
          })
          //2.2 新增标签(如果没有完全匹配,则新增)
          if(!this.allTags.find(x=>x === searchQuery))
            options.push({
              id: searchQuery,
              label: searchQuery,
              isNew: this.isNewTagDifference
            })
        }
        //3. 回传
        callback(null, options)
      }
    },
    //选择菜单项后强行清空搜索字符串
    selectItem(){
      if(this.clearOnSelect)
        this.$refs.tagSelectRef.resetSearchQuery();
    }
  }
}
</script>

在使用时:

    <!--引用部分(vue文件)-->
    <tag-select
      v-model="value"
      :allTags="allTags"
    />

另外,在下拉框中始终展示已经选中的自定义项,暂时还没实现。

 

https://gitee.com/yuguifang/tag-select

Logo

前往低代码交流专区

更多推荐