【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('')
    }

 

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