VUE - 搜索多选下拉框组件

本文记录了一个Vue组件,实现了带有搜索功能的多选下拉框。组件支持搜索、多选,并在重新搜索后能保留已选择的选项。引用了ElementUI的相关文档并展示了组件的效果和源码。

VUE - 搜索多选下拉框组件

Max.Bai

2020-04

 

记录一个多选搜索下拉框组件

功能:

1. 支持搜索,

2. 多选,

3. 重新搜索依旧保留已选的选项

ElementUI 组件文档 https://element.eleme.cn/2.12/#/zh-CN/component/select

效果

源码:

<template>
  <el-select
    v-model="localUserIDs"
    multiple
    filterable
    size="small"
    :placeholder="placeholder"
    class="text-select-hidden"
    style="width:100%;height:33px;"
    :loading="loading"
    :multiple-limit="15"
    remote
    :remote-method="remoteSearchUser"
  >
    <el-option
      v-for="item in localUserOptions"
      :key="item.value"
      :label="item.label"
      :value="item.value"
      :disabled="item.disabled"
    >
      <span style="float: left">{{ item.label }}</span>
      <span
        style="float: right; color: #8492a6; font-size: 13px;padding-right:20px;"
      >{{ item.dept_path_names }}</span>
    </el-option>
  </el-select>
</template>

<script>
// 远程搜索接口 返回 {"value":123, label:"max.bai", "dept_path_names": "集团/技术"}
import { baseusername } from "@/api/base";

export default {
  name: "userSelecte",
  props: {
    userIds: {
      // 已选的值
      type: Array,
      default() {
        return [];
      }
    },
    userNames: {
      // 已选的文本
      type: Array,
      default() {
        return [];
      }
    },
    userOptions: {
      // 默认选项 可以没有
      type: Array,
      default() {
        return [];
      }
    }
  },
  data() {
    return {
      placeholder: "请输入姓名搜索",
      loading: false,
      localUserIDs: this.userIds, // selected value list
      localUserNames: this.userNames, // selected label list
      localUserOptions: this.userOptions, // select options
      selectedUserOptions: [] // 已选用户选项  selected options
    };
  },
  mounted: function() {
    this.loadUsers(true);
  },
  watch: {
    // 观察选择值,变化更新 selected options,同时更新父组件值
    localUserIDs: {
      deep: true,
      handler: "refreshSelectedUser"
    }
  },
  methods: {
    async loadUsers(init) {
      // 首次加载,查询已选用户,添加到选项中,添加默认选项,添加提示
      if (this.localUserIDs.length > 0) {
        this.loading = true;
        const { data } = await baseusername({ usernames: this.localUserIDs });
        this.selectedUserOptions = data;

        if (init) {
          this.localUserOptions = this.selectedUserOptions
            .concat(this.userOptions)
            .concat([
              {
                value: "-1",
                label: this.placeholder,
                disabled: true
              }
            ]);
        }
        this.loading = false;
      }
    },
    refreshSelectedUser() {
      // 刷新已选用户
      if (this.localUserIDs.length > 0) {
        // update selected options
        this.selectedUserOptions = [];
        for (let j = 0; j < this.localUserOptions.length; j++) {
          if (this.localUserIDs.includes(this.localUserOptions[j].value)) {
            this.selectedUserOptions.push(this.localUserOptions[j]);
          }
          if (this.selectedUserOptions.length >= this.localUserIDs.length) {
            break
          }
        }
      } else {
        this.selectedUserOptions = [];
      }
      this.updateParentData();
    },
    updateParentData() {
      // 更新父组件value
      this.$emit("update:userIds", this.localUserIDs);

      // 更新父组件label
      this.localUserNames = [];
      for (let i = 0; i < this.selectedUserOptions.length; i++) {
        this.localUserNames.push(this.selectedUserOptions[i].label);
      }
      this.$emit("update:userNames", this.localUserNames);
    },
    async remoteSearchUser(query) {
      // 远程搜索
      if (query !== "") {
        this.loading = true;
        const { data } = await baseusername({ name: query });
        // 更新选项,添加已选择选项
        this.localUserOptions = JSON.parse(
          JSON.stringify(this.selectedUserOptions)
        );
        // 更新选项,添加不包含已选的选项
        for (let i = 0; i < data.length; i++) {
          let find = false;
          for (let j = 0; j < this.selectedUserOptions.length; j++) {
            if (data[i].value == this.selectedUserOptions[j].value) {
              find = true;
              break;
            }
          }
          if (!find) {
            this.localUserOptions.push(data[i]);
          }
        }
        this.loading = false;
      }
    }
  }
};
</script>

<style>
</style>

父组件使用:

            <UserSelect
                    :userIds.sync="editProductInfo.product_owner_ids"      //已选值列表
                    :userNames.sync="editProductInfo.product_owner_names"  //已选文本列表
                    :userOptions="userOptions"    // 默认选项列表
                  />

 

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值