当前位置:首页 » 《关于电脑》 » 正文

vue2 ant-design select组件自定义下拉框, dropdownRender 使用,以及遇到的坑

7 人参与  2024年11月14日 19:21  分类 : 《关于电脑》  评论

点击全文阅读


业务需求:下拉框需要满足用户可输入筛选 和 点击右侧 字符按钮 #A-Z进行用户选择

1、基础页面代码

<div>    <a-select      style="width: 100%"      placeholder="请选择客户"      allow-clear      show-search      :filter-option="false"      :not-found-content="fetching ? undefined : null"      :defaultActiveFirstOption="false"      :getPopupContainer="getPopupContainer"      @search="searhcCust"      @dropdownVisibleChange="dropdownVisibleChange"    >      //dropdownRender 插件使用,自定义右边      <div        slot="dropdownRender"        slot-scope="menu"      >        <div class="index-bar">          <div            v-for="letterItem in letter"            :key="letterItem"            @click.prevent="scrollOn(letterItem)"            class="index-letter"            @mousedown="e => e.preventDefault()" // 阻止调用默认事件          >            {{ letterItem }}          </div>        </div>        <v-nodes :vnodes="menu" /> // 注意要在components中定义      </div>      <a-select-opt-group        v-for="(group, index) in peoArray"        :key="index"      >        <span          slot="label"          class="option-letter"          :id="'peo_' + componentId + group.key"        >{{group.key}}</span>        <a-select-option          v-for="option in group.list"          :key="option.custRowId"          :value="option.custRowId"          :title="option.custName"        >          <span>{{ option.custName }}</span>        </a-select-option>      </a-select-opt-group>    </a-select>  </div>

2、script中的代码

<script>import { debounce } from 'lodash'export default {  props: {    componentId: { // 设置不同的id,用于同页面有多个此组件时锚点不生效      type: String,      default: ''    }  },  components: {    VNodes: {      functional: true,      render: (h, ctx) => ctx.props.vnodes,    }  },  data() {    return {      dropOpen: false,      searchValue: '',      navBarHeight: '50px', // 导航栏高度      letter: [], // 字母检索列表      peoArray: [], // 通讯录列表      custList: null,      custRowId: undefined,      fetching: false,      debounceGetCustInfoKeyList: null,    }  },  created() {    this.getCustInfoKeyList()    this.debounceGetCustInfoKeyList = debounce(this.getCustInfoKeyList, 500)  },  methods: {    dropdownVisibleChange(open) {      this.dropOpen = open    },    getPopupContainer(triggerNode) {      if (this.modalSelect) {        return triggerNode.parentNode      } else {        return document.body      }    },    changeCust(val) {      this.$emit('change', val)    },    getList(peoArray) {      let newList = []      peoArray.forEach(element => {        newList.push(...element.list)      })      return newList    },    searhcCust(val) {      this.searchValue = val      this.debounceGetCustInfoKeyList()    },    getCustInfoKeyList() {      const params = {        custName: this.searchValue,      }      this.$http.XXX(params).then(res => {        if (res.code === 200) {          this.custList = res.data          if (this.custList) {            this.setList()          } else {            this.peoArray = []          }          this.fetching = false        } else {          this.$message.warn(res.msg)          this.fetching = false        }      })    },    setList() {      let list = []      this.letter = []      for (const key in this.custList) {        this.letter.push(key)        list.push({          key,          list: this.custList[key]        })      }      setTimeout(() => {        this.peoArray = list      })    },    // 字母检索    scrollOn(item) {      let target = document.getElementById('peo_' + this.componentId + item) // 获取每个字母通讯录对象      if (target) {        const scrollDom = document.getElementsByClassName('ant-select-dropdown-menu')[0]        scrollDom.scrollTo({          behavior: 'smooth',          top: target.offsetTop - 10        })      } else {        this.$message.warn(`当前${item}元素下暂无客户`)      }    }  }}</script>

3、基础CSS代码

.index-bar {  position: absolute;  z-index: 99;  right: 10px;  top: 50%;  transform: translateY(-50%);  display: flex;  flex-direction: column;  align-items: center;}.index-letter {  margin: 0;  cursor: pointer;  color: #1677ff;  font-weight: 500;  font-size: 12px;  line-height: 20px;}.option-letter {  font-weight: 600;  color: rgba(0, 0, 0, 0.45);}

4、遇到的坑是什么呢?
就是在同一个页面,渲染同一个组件时,在点击前一个组件后,后面的组件右侧按钮滚动失效。
造成这个问题的原因就是 dropdownRender 渲染不会销毁,导致scrollOn获取到的DOM是同一组数据,解决方法有两种:

// 1、在 dropdownRender 插件的地方<div      v-if="dropOpen"       slot="dropdownRender"       slot-scope="menu"     >     // 2、scrollOn 中修改查询Dom方法     let target = document.getElementById('peo_' + this.componentId + item) // 获取每个字母通讯录对象     if (target) {        const parentDom = document.getElementById(offsetParent.id)        const scrollDom = parentDom.children[0]        scrollDom.scrollTo({          behavior: 'smooth',          top: target.offsetTop - 10        })      } else {        this.$message.warning(`当前${item}元素下暂无客户`)      }

点击全文阅读


本文链接:http://m.zhangshiyu.com/post/186223.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1