業務需求:下拉框需要滿足用戶可輸入篩選 和 點擊右側 字符按鈕 #A-Z進行用戶選擇
1、基礎頁面代碼
<div><a-selectstyle="width: 100%"placeholder="請選擇客戶"allow-clearshow-search:filter-option="false":not-found-content="fetching ? undefined : null":defaultActiveFirstOption="false":getPopupContainer="getPopupContainer"@search="searhcCust"@dropdownVisibleChange="dropdownVisibleChange">//dropdownRender 插件使用,自定義右邊<divslot="dropdownRender"slot-scope="menu"><div class="index-bar"><divv-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-groupv-for="(group, index) in peoArray":key="index"><spanslot="label"class="option-letter":id="'peo_' + componentId + group.key">{{group.key}}</span><a-select-optionv-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 = valthis.debounceGetCustInfoKeyList()},getCustInfoKeyList() {const params = {custName: this.searchValue,}this.$http.XXX(params).then(res => {if (res.code === 200) {this.custList = res.dataif (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 插件的地方<divv-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}元素下暫無客戶`)}