【antdesign select】下拉选择-带选择序号

需求:下拉框在选中时能够在check-icon后面显示当前选中项的排序,以及当超过最大可选数时不允许继续选中。

在Antdesign组件里好像没有控制可选数的option,这点真的让人很奇怪诶~还得自己在onchange里写逻辑来控制。

一开始我能想到的简单思路是:

1.通过在属性options里面塞个icon,自定义选项的展示

2.通过操作渲染好的下拉列表里的dom元素

实践后发现上述的都不太可行,最后只能采用了自定义下拉框内容(dropdownRender属性)来实现。

放一下代码template

<template #dropdownRender="{list}">
      <v-nodes :vnodes="list" />
      <a-list :locale="{emptyText: notFoundContent}" @mousedown.prevent>
        <li
          v-for="item in filteredDataSource"
          :key="item.id"
          :value="item.id"
          class="sort-select-list-item"
          :class="{'disabled':item.disabled,'selected':item.selected}"
          @click="handleClickItem(item)"
          @mouseenter="handleMouseEnterItem(item)"
          @mouseleave="handleMouseLeaveItem(item)"
        >
          {{ item.name }}
          <a-icon v-if="item.selected" class=" check-icon check-icon-selected" type="check" />
          <a-icon v-else v-show="item.hovered && !item.disabled" class=" check-icon check-icon-hovered" type="check" />
          <span v-if="item.selected" :class="{'check-order-circle': item.selected}" class="check-icon-selected">
            <span class=" check-order ">{{ item.order }}</span>
          </span>
          <span v-else v-show="item.hovered && !item.disabled" class="check-order-circle-hovered check-icon-hovered">
            <span class=" check-order ">{{ item.order }}</span>
          </span>
        </li>
      </a-list>
    </template>

可以看到,实际上就是自定义下拉框用了个list组件,并且通过状态属性disabled、selected、hovered来控制这些选项的样式

这样子改写了antdesign的下拉列表展示后,就得重新写一遍样式和交互,才能保持和原有样式一致。

现在说一下思路:

调用这个组件

传入属性:dataSource

获取到dataSource后,不会直接用来渲染模板。需要处理成新的dataSource,给它添加些基础状态属性。

// 新的dataSource(接收prop,添加相关属性后的dataSource,主要用于数据处理)
get newDataSource() {
  const data: any = this.dataSource.map((item: any) => {
    return {
      ...item,
      selected: false,
      disabled: false,
      hovered: false,
      order: 1
    }
  })
  this.filteredDataSource = data
  return data
}

这里还有个filteredDataSource变量,在上一张图可以看到,实际模板最后渲染的list数据是来自filteredDataSource的。

这个就是为了允许这个下拉框可以有搜索功能。

结合Antdesign的原生下拉组件中的search事件来实现

// 搜索匹配相应的信息
handleSearch(value: any) {
  if (value) {
    this.filteredDataSource = this.newDataSource.filter((item: any) => {
      if (item.name.includes(value))
        return true
    })
  } else {
    this.filteredDataSource = this.newDataSource
  }
}

之后就是针对鼠标事件(点击、移入、移除)来修改对应的状态属性值,从而实现选中、hovered、和禁止选择的样式。

而对于选中事件,需要考虑的点相对复杂些。

  1. Antdesign的原生下拉组件,在点击选中时可以控制是否清空输入框的输入内容(不好实现)
  2. 点击项原本为选中,再次点击时就是取消点击
  3. 选中时更新下拉框的value,否则下拉列表和下拉框的选中项会不一致
  4. 选中后是否启用禁用

遇到的问题:

问题1.当鼠标点击下拉框,下拉列表出现,然后快速hover到列表项时会出现下拉列表抖动的问题,这我就很奇怪了,发现在这个过程中下拉列表渐现渐隐的动画执行了两遍。

之所以会被执行两次,我猜测了下:应该是在这个hover过程中,我对下拉列表的hover列表项的状态属性修改了,对应的列表项时会有选中样式以及序号icon,就导致下拉列表重新渲染,与此同时动画执行了一半。又被重新执行了。

一开始是思考:

1.看看在hover事件时延时赋值,但这就导致整体功能看起来有卡顿延时。

2.在下拉框刚点击的几秒内不允许hover,但这样代码上,每个列表项就需要判断什么时候是下拉框点击的几秒内。不太知道怎么来判断

最后尝试性打印了antdesign的下拉框元素,神奇的发现有个控制动画的属性,于是思考能否将这个值置为空,成功解决了这个问题。

问题2.当下拉框允许搜索且键入了搜索关键字后,下拉列表项被过滤展示后,点击选中任一下拉项后,搜索框的内容没有被清空。

在antdesign下拉组件中是有这个属性的设置,可以用于是否自动清空搜索框的。

// 如果允许清空,清空输入框输入的内容(todo)
    if (this.autoClearSearchValue) {
      (this.$refs.sortSelect as any).$children[0].$children[0].setInputValue('')
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章