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

hhh 2024-10-01 15:33:04 阅读 54

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

1、基础页面代码

<code><div>

<a-select

style="width: 100%"code>

placeholder="请选择客户"code>

allow-clear

show-search

:filter-option="false"code>

:not-found-content="fetching ? undefined : null"code>

:defaultActiveFirstOption="false"code>

:getPopupContainer="getPopupContainer"code>

@search="searhcCust"code>

@dropdownVisibleChange="dropdownVisibleChange"code>

>

//dropdownRender 插件使用,自定义右边

<div

slot="dropdownRender"code>

slot-scope="menu"code>

>

<div class="index-bar">code>

<div

v-for="letterItem in letter"code>

:key="letterItem"code>

@click.prevent="scrollOn(letterItem)"code>

class="index-letter"code>

@mousedown="e => e.preventDefault()" // 阻止调用默认事件code>

>

{ -- -->{ letterItem }}

</div>

</div>

<v-nodes :vnodes="menu" /> // 注意要在components中定义code>

</div>

<a-select-opt-group

v-for="(group, index) in peoArray"code>

:key="index"code>

>

<span

slot="label"code>

class="option-letter"code>

:id="'peo_' + componentId + group.key"code>

>{ -- -->{ group.key}}</span>

<a-select-option

v-for="option in group.list"code>

:key="option.custRowId"code>

:value="option.custRowId"code>

:title="option.custName"code>

>

<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"code>

slot="dropdownRender"code>

slot-scope="menu"code>

>

// 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}元素下暂无客户`)

}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。