適用場景
在項目中肩民,我們需要運用到很多來自后端返回的數(shù)據(jù)蔽豺。有時是上百條跷车,有時甚至上千條棘利。如果加上后端的多表查詢或者數(shù)據(jù)量過大,這就導致在前端的顯示就會及其慢朽缴,特別是在網(wǎng)絡不好的時候更是如此善玫。所以分頁展示就是一種較好的交互體驗了。
功能基本介紹
- 基于
element-ui
的el-select
實現(xiàn)的密强。 - 已封裝成組件茅郎,可以實現(xiàn)單選、多選或渤、遠程搜索系冗、滾動分頁加載數(shù)據(jù)、數(shù)據(jù)回顯薪鹦。
效果
微信截圖_20210727173019.png
上代碼
組件代碼:
<template>
<el-select
v-model="selectedValue"
v-loadData="loadData"
remote
filterable
:remote-method="remoteMethod"
class="more-select"
:popper-class="`more-select-dropdown ${loading && 'loading'}`"
:multiple="multiple"
:clearable="clearable"
@change="selectChange"
>
<!-- 只有isShow定義了false掌敬,才進行隱藏,否則正常顯示 -->
<el-option
v-for="(item,index) in list"
v-show="item.isShow===false?false:true"
:key="item.value + `'${index}'`"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
<script>
import Vue from 'vue'
Vue.directive(
'loadData',
{
bind(el, binding) {
// 獲取element-ui定義好的scroll盒子
const SELECTWRAP_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
SELECTWRAP_DOM.addEventListener('scroll', function() {
/**
* scrollHeight 獲取元素內容高度(只讀)
* scrollTop 獲取或者設置元素的偏移值,常用于, 計算滾動條的位置, 當一個元素的容器沒有產生垂直方向的滾動條, 那它的scrollTop的值默認為0.
* clientHeight 讀取元素的可見高度(只讀)
* 如果元素滾動到底, 下面等式返回true, 沒有則返回false:
* ele.scrollHeight - ele.scrollTop === ele.clientHeight;
*/
const condition = this.scrollHeight - this.scrollTop <= this.clientHeight
//監(jiān)聽下拉框是否滾動到底部池磁,滾動到底部就加載下一頁數(shù)據(jù)
if (condition) binding.value()
})
}
}
)
export default {
props: {
// 默認選中值
selectedValue: {
type: [Array, String, Number],
default: ''
},
// 默認選中值對應的數(shù)據(jù)奔害,用于回顯
defaultSelectedStr: {
type: Array,
default: () => ([])
},
// 是否可以多選
multiple: {
type: Boolean,
default: false
},
// 是否可以清空
clearable: {
type: Boolean,
default: false
},
// 遠程搜索時,輸入框搜索值的鍵名
searchKey: {
type: String,
default: 'searchKey'
},
// 獲取下拉框值得方法名
getListMethods: {
type: Function,
default: null
},
// 獲取下拉框值時 默認參數(shù)
getListParams: {
type: Object,
default: () => ({})
},
// 下拉框值的格式
getListFormat: {
type: Function,
default: (data) => {
return data.map(({ label, value }) => ({ label, value }))
}
}
},
data() {
return {
list: [],
activeValue: '',
searchText: '',
pageNum: 1,
pageSize: 10,
loading: false,
finished: false // 是否加載完所有數(shù)據(jù)
}
},
watch: {
// 默認選中值
defaultSelected: {
handler() {
this.activeValue = this.defaultSelected
},
immediate: true
},
// 將選中的數(shù)據(jù) 拼成數(shù)組地熄,放在list中华临,用于解決回顯時 非第一頁數(shù)據(jù)無法正常顯示的問題
defaultSelectedStr: {
handler() {
this.list = this.list.concat(this.defaultSelectedStr)
},
immediate: true
}
},
created() {
this.getData()
},
methods: {
getData() {
if (!this.getListMethods || this.finished) return
this.loading = true
const params = {
...this.getListParams,
[this.searchKey]: this.searchText,
pageNum: this.pageNum,
pageSize: this.pageSize
}
this.getListMethods(params).then(({ data }) => {
// 對數(shù)據(jù)進行格式化
data = this.getListFormat(data)
// 判斷是否是最后一頁了
if (data.length < this.pageSize) this.finished = true
this.list = this.list.concat(data)
}).finally(() => {
this.loading = false
})
},
searchMethod(searchText) {
if (searchText === this.searchText) return
// 防抖處理
let timeout = null
clearTimeout(timeout)
timeout = setTimeout(() => {
this.list = []
this.pageNum = 1
this.finished = false
this.searchText = searchText
this.getData()
}, 500)
},
loadData() {
// 防抖處理
let timeout = null
clearTimeout(timeout)
timeout = setTimeout(() => {
if (this.finished) return
this.pageNum += 1
this.getData()
}, 500)
},
reset() {
this.activeValue = ''
},
selectChange(value) {
console.log(value)
this.$emit('selectedChange', value)
}
}
}
</script>
使用示例:
<template>
<div>
<ScrollSelect
:selected-value="value"
:default-selected-str="valueStr"
:get-list-methods="getListMethods"
:get-list-format="getListFormat"
:get-list-params="getListParams"
:clearable="true"
:multiple="true"
search-key="keyword"
@selectedChange="selectedChange"
/>
</div>
</template>
<script>
import ScrollSelect from './_modules/scroll-select'
import { queryList } from '@/api/index'
export default {
components: {
ScrollSelect
},
data() {
return {
value: [],
valueStr: [],
getListMethods: queryList,
getListFormat: ({ list = [] }) => { // 下拉框數(shù)據(jù)格式
return list.map(({ name, id: value }) => ({ label: name, value }))
},
getListParams: { // 下拉框接口默認參數(shù)
isDisabled: 0
}
}
},
mounted() {
// 設置默認選中的值
this.value = [1, 12]
this.valueStr = [{
name: 'test',
id: 1,
isShow: false
}, {
name: '選中的',
id: 12,
isShow: false
}]
},
methods: {
selectedChange(ids) {
this.value = ids
}
}
}
</script>