业务需求:下拉框需要满足用户可输入筛选 和 点击右侧 字符按钮 #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'exportdefault{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 inthis.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}元素下暂无客户`)}
版权归原作者 hhh 所有, 如有侵权,请联系我们删除。