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}元素下暂无客户`)
}
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。