elementUI 使用 el-select 的远程搜索功能,导致数据无法回显怎么解决?

elementUI 使用 el-select 的远程搜索功能,导致数据无法回显怎么解决?,第1张

如果有同学还没用过这个功能,可以先了解下:

使用场景

大部分情况下使用 el-select 的时候,el-options 中 options 的值都是后端接口给的数据,直接赋值就可以了。但是有的时候数据量比较大,比如几千甚至上万条的时候,如果直接赋值,整个页面的 dom 会被撑爆,不仅请求全量数据接口的时候时间会很久,而且赋值完之后整个页面会非常卡。

解决方法

现在的 elementPlus 已经有虚拟化选择器了,直接使用,非常方便,如果你使用的是Vue3,可以直接移步 elementPlus官方文档

如果你使用的是 Vue2,很可惜没有现成的组件能够使用。解决方法一共两个,都是需要后端配合前端进行修改的:

  • 后端将接口改为分页的形式;前端将选择器下拉框中的数据改为滚动加载
  • 后端将接口改为模糊搜索的形式,通过选择器中输入的内容去搜索模糊匹配的数据然后返回;前端使用 elementUI 中选择器的远程搜索功能,用户在选择器输入内容后才发起请求

本次主要讲解使用远程搜索来解决的方法,前端代码就直接放出了,不过多解释:

<el-select ref="selectDom" v-model="form.diagnosisIds" :remote-method="remoteMethod" placeholder="请选择" clearable filterable multiple remote @visible-change="templateTagChange">
  <el-option
    v-for="item in relationList"
    :key="item.id"
    :label="item.name"
    :value="item.id"
  />
el-select>

<script>
export default {
  data: {
  	return {
  	  form: {
        diagnosisIds: [] // v-model 中绑定的值
      },
      relationList: [] // 下拉框的数据
    }
  },
  methods: {
    // 远程搜索方法,数据太多,不能直接渲染
    remoteMethod(query) {
      if (query !== '') {
        this.relationList = []
        this.loading = true
        // 这个方法可以做下节流处理,不需要一输入就发起请求,这里偷懒没有写
        getDiagnoseInfo({ diagnoseName: query }).then(res => {
          this.loading = false
          this.relationList = res.filter(item => {
            return item.name.toLowerCase()
              .indexOf(query.toLowerCase()) > -1
          })
        })
      } else {
        this.relationList = []
      }
    },
    // 诊断选择器下拉框隐藏时触发事件,清空数据
    templateTagChange(val) {
      if (val === false) {
        this.relationList = []
      }
    }
  }
}
script>
带来的问题

之前直接赋值选择器选项的时候,因为页面加载完选择器的选项就有内容了,所以数据回显的时候一般后端返回id,选择器会自动匹配选项中那一项id对应的name值并回显。但是现在使用远程搜索,页面刚加载完用户不在选择器输入的话,选择器选项一直都是空的,自然也无法进行匹配回显。你会发现这时候只是id回显到选择器中,并不是回显id所匹配的name。那么该怎么解决呢?

如何解决回显问题

首先需要后端配合改一下接口,原本的接口是返回id的字符串,现在需要后端那边匹配一下对应id的name,然后返回id与name的集合,形如 { id: 1, name: 'xxx' };然后前端这里有两种解决方法:

1. 给选择器选项赋值

既然是因为选择器选项为空无法进行匹配回显,那就在页面加载完后给选择器选项赋值就好了:

const ids = [] // 专门用来存放选项id的数据
const strs = [] // 专门用来存放选项name的数据
// res.tagMapList 为接口返回的id与name的集合数据
res.tagMapList.forEach(ele => {
  ids.push(ele.id)
  strs.push(ele.value)
})
for (let i = 0; i < strs.length; i++) {
  this.form.diagnosisIds.push(ids[i]) // 给选择器v-model赋值,由于是支持多选的,所以会是一个数据
  // 给选择器的选项赋值,接可以自己匹配上name了
  this.relationList.push({
    id: ids[i],
    name: strs[i]
  })

效果如下:

会发现确实成功回显name了,但是当鼠标聚焦在选择器上且未发起远程搜索时,这个下拉框会出现这几项的值(理所应当的问题,因为给选项赋了这几个值嘛,但是在未发起远程搜索之前是不需要这个下拉框的)

2. 使用源码中的 cachedOptions 方法隐藏下拉框中的内容

有兴趣的可以自行查阅elementUI这部分的源码,简而言之就是源码中是利用cachedOptions方法将当前的下拉选项隐匿储存的集合,那我们可以通过在这个集合中把我们需要显示的选项添加进去

放出代码:

const ids = []
const strs = []
res.tagMapList.forEach(ele => {
  ids.push(ele.id)
  strs.push(ele.value)
})
for (let i = 0; i < strs.length; i++) {
  this.form.diagnosisIds.push(ids[i])
  this.$refs.selectDom.cachedOptions.push({
    currentLabel: strs[i],
    currentValue: ids[i],
    label: strs[i],
    value: ids[i]
  })
}

效果如下:

搞定 ~

参考资料:vue element Select组件远程搜索绑定值为对象时,编辑状态如何回显显示正确的label

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/725087.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-26
下一篇 2022-04-26

发表评论

登录后才能评论

评论列表(0条)

保存