el-select使用远程搜索功能+多选+选项采用checkbox处理方法

657 阅读2分钟

场景:采用工el-select方式搜索企业下的用户,并且采用多选的方式,选中的选项可回显展示在输入框中,且下拉选项需要带上checkbox方式。

el-select提供了远程搜索和多选功能,但选项中需要自定义添加el-checkbox方式,但由于点击选项后自动会触发change事件,且添加后的选项点击删除,选择框不能对应删除,所以需要禁用el-select点击选项后的事件,采用@click.stop的方式,且在样式上将选项的长度延伸至100%。防止点击其他空白触发事件。

为了统一格式,在回显时赋值的数据和绑定的数据格式需要统一,采用{accountId, loginName}的方式,其中buildItem方法,以及handleChange中都有所体现。 截屏2023-12-19 13.46.49.png

截屏2023-12-19 13.50.54.png

接下来又发现无法回显tag数据,这是因为采用了远程搜索的方式,选择器没有选项,无法对应匹配内容,也就导致输入框中的tag无法回显。可采用以下解决方法: 源码中是利用cachedOptions方法将当前的下拉选项隐匿储存的集合,我们可以通过在这个集合中把我们需要显示的选项添加进去。

其中selectedList为需要回显的原始数据,selectedAccount为处理后需要回显的数据,selectDom为选择器dom。 截屏2023-12-19 14.04.03.png

主要代码如下:

      <el-select
        ref="selectDom"
        v-model="selectedAccount"
        multiple
        remote
        filterable
        placeholder="请输入"
        :remote-method="searchOptions"
        :loading="loading"
        popper-class="select-account"
        value-key="accountId"
      >
        <el-option
          v-for="item in options"
          :key="item.accountId"
          :label="item.loginName"
          :value="buildItem(item)"
        >
          <p @click.stop class="check-option">
            <el-checkbox
              :value="
                selectedAccount.filter((it) => it.accountId == item.accountId)
                  .length > 0
              "
              :key="item.accountId"
              @change="
                handleChange($event, `${item.accountId},${item.loginName}`)
              "
              >{{ item.loginName }}</el-checkbox
            >
          </p>
        </el-option>
      </el-select>
      
      
   watch: {
    selectedList: {
      handler(val) {
        if (val && val.length) {
          //解决远程搜索分页导致无法回显tag问题
          this.$nextTick(() => {
            val.forEach((item) => {
              this.selectedAccount.push({
                accountId: item.accountId,
                loginName: item.loginName
              })
              this.$refs.selectDom.cachedOptions.push({
                currentLabel: item.loginName,
                currentValue: {
                  accountId: item.accountId,
                  loginName: item.loginName
                },
                label: item.loginName,
                value: {
                  accountId: item.accountId,
                  loginName: item.loginName
                }
              })
            })
          })
        }
      }
    }
  },
  methods: {
    async getSelectOptions() {
      //远程搜索
      this.options = xxxx
    },
    buildItem(item) {
      return {
        accountId: item.accountId,
        loginName: item.loginName
      }
    },
    handleChange(check, val) {
      if (!val) return
      let accountId = val.split(',')[0]
      let loginName = val.split(',')[1]
      //check为true表示选中则添加,为false表示不选中则删除
      if (check) {
        this.selectedAccount.push({
          accountId,
          loginName
        })
      } else {
        this.selectedAccount = this.selectedAccount.filter(
          (item) => item.accountId !== accountId
        )
      }
    },
    searchOptions(val) {
      if (val) {
        this.searchVal = val
        this.getSelectOptions()
      }
    }
   }
   
   
   <style lang="less">
    .select-account {
      li {
        padding: 0 !important;
        .check-option {
          padding: 0 8px;
        }
        label {
          width: 100%;
        }
        &:after {
          display: none;
        }
      }
    }
    </style>