博客地址:https://ainyi.com/63
昨天偶然看到評論區一位老哥的需求,一時興起,就答應了當天寫好源碼寫個博客
回來的晚,第二天才寫好。。
寫個分頁的穿梭框,從而解決數據量龐大的問題
我之前寫過一篇博客:關于 Element 組件的穿梭框的重構 介紹并實現的方法
但是第二個分頁的 demo 沒有,在上一家公司匆匆解決后,沒有寫入自己的 GitHub,有點可惜...
當時可是在上班,而且太忙了,不過既然答應了這位老哥寫個 demo,就要做到,也是給自己一個挑戰
進入正題
看實現效果圖
既然之前博客談過,這里就不仔細談了,主要放主要的源碼
問題
Element 官方組件目前(==18年==)明顯對于多選==三級聯動的穿梭框==沒有解決方案,也對==數據量龐大的穿梭框==沒有結局方案(各位看官可以試一下,放入幾千條數據到穿梭框,卡到爆...),遂只能自己重寫組件,完成業務需求
功能
實現分頁搜索,做成在所有數據里搜索,不是在當前分頁的數據里搜索,這樣就不用在每個分頁都搜索一次了。搜索后的結果也會自動分頁。(全部數據和僅作展示的數據存都是存放在不同變量)全選只在當前頁里的全選穿梭框左右兩個框的聯動關鍵點
每個框作為一個子組件(組件化思想)分頁關鍵判斷臨界點搜索,監聽 keyword 的變化,傳遞到父組件搜索,從全局數據搜索把備選的數據當做已選的過濾數組,把已選的數據當做備選的過濾數組,在全局 data 進行過濾,最后再進行一次搜索(備選、已選)(考慮到是在搜索過后點擊的)中間的左右箭頭(加入已選和移除已選)放在父組件控制數據流動數據流動:子備選框 -> 父組件 -> 子已選框 (移除已選相反)源碼
Districts.vue(包裹兩個穿梭框的父組件)export default {props: {data: {type: Array,},},data () {return {dataList: [], // 未選中(已過濾出已選)的數據selectList: [], // 已選中的數據,傳遞到子組件的數據dataListNoCheck: [], // 未選中的(或已搜索)傳遞到子組件的數據selectListCheck: [], // 已選中的(或已搜索)傳遞到子組件的數據checkData: [], // 已勾選的數據(待添加或刪除數據)noSelectkeyword: '',haSelectkeyword: '',disablePre: true,disableNex: true,};},created () {this.getDistrict();},methods: {// 分頁數據getDistrict () {this.dataList = this.data;this.dataListNoCheck = this.dataList;},searchWord (keyword, titleId) {// 過濾掉數據,保留搜索的數據if (titleId === 0) {this.noSelectkeyword = keyword;this.dataListNoCheck = this.dataList.filter(val => val.name.includes(keyword));} else {this.haSelectkeyword = keyword;this.selectListCheck = this.selectList.filter(val => val.name.includes(keyword));}let refsName = titleId === 0 ? 'noSelect' : 'hasSelect';// 延遲執行setTimeout(() => {this.$refs[refsName].getDistrict();}, 0);},// 檢查左右按鈕可用性checkDisable (data, id) {if (id === 0) {data.length > 0 ? (this.disableNex = false) : (this.disableNex = true);} else {data.length > 0 ? (this.disablePre = false) : (this.disablePre = true);}},// 選擇checkSelect (val) {this.checkData = val;},// 關鍵:把未選擇的數據當做已選擇的過濾數組,把已選擇的數據當做未選擇的過濾數組,在全局data進行過濾,最后進行一次搜索// 添加至已選addData () {let dataFilter = [...this.selectList,...this.checkData,];this.dataList = this.data.filter(item1 => {return dataFilter.every(item2 => item2 !== item1);});this.selectList = this.data.filter(item1 => {return this.dataList.every(item2 => item2 !== item1);});// 搜索一次this.searchWord(this.noSelectkeyword, 0);this.searchWord(this.haSelectkeyword, 1);},// 從已選中刪除deleteData () {let dataFilter = [...this.dataList,...this.checkData,];this.selectList = this.data.filter(item1 => {return dataFilter.every(item2 => item2 !== item1);});this.dataList = this.data.filter(item1 => {return this.selectList.every(item2 => item2 !== item1);});// 搜索一次this.searchWord(this.noSelectkeyword, 0);this.searchWord(this.haSelectkeyword, 1);},},components: {Transfer,},
};
</script>
Transfer.vue(穿梭框子組件)export default {props: {titleId: {type: Number,},districtList: { // 父組件傳遞的數據type: Array,},},data () {return {title: ['渠道', '已選中'],districtListMock: [], // 展示的數據 (搜索和分頁會自動修改這個數組)checkedCities: [], // 已選擇,數據格式:[id,id,id...]isIndeterminate: false,checkAll: false,searchWord: '',len: 0,total: 0,pageIndex: 0,disabledPre: true,disabledNex: false,};},created () {this.getDistrict();},watch: {// 搜索框的監聽器searchWord (newWord) {this.$emit('search-word', newWord, this.titleId);},// districtListMock 和 checkAll 的監聽器districtListMock () {// 當方框中無已選擇的數據時,不能勾選checkBoxif (this.checkedCities.length === 0) {this.checkAll = false;this.isIndeterminate = false;}},checkedCities (newWord) {this.$emit('check-disable', newWord, this.titleId);},// 當列表中無數據時,不能勾選checkBoxcheckAll () {this.checkAll = this.districtListMock.length === 0 ? false : this.checkAll;},},methods: {// 分頁數據getDistrict () {this.len = this.districtList.length;this.total = Math.ceil(this.len / 200);this.pageIndex = 0;this.pageData();},pageData () {this.checkedCities = [];if (this.total > 1 && this.pageIndex < (this.total - 1)) {this.pageIndex === 0 ? this.disabledPre = true : this.disabledPre = false;this.disabledNex = false;this.districtListMock = this.districtList.slice(this.pageIndex \\* 200, this.pageIndex \\* 200 + 200);} else {this.total > 1 ? this.disabledPre = false : this.disabledPre = true;this.disabledNex = true;this.districtListMock = this.districtList.slice(this.pageIndex \\* 200, this.len);}},// 上一頁prev () {this.pageIndex > 0 && --this.pageIndex;this.pageData();},// 下一頁next () {this.pageIndex <= (this.total - 1) && ++this.pageIndex;this.pageData();},// 單選handleCheckedChange (value) {let checkedCount = value.length;this.checkAll = checkedCount === this.districtListMock.length;this.isIndeterminate = checkedCount > 0 && checkedCount < this.districtListMock.length;// 子傳父this.$emit('check-district', value);},// 全選handleCheckAllChange (val) {this.checkedCities = val ? this.districtListMock.map(val => val) : [];this.isIndeterminate = false;// 子傳父this.$emit('check-district', this.checkedCities);},},
};
</script>
具體源碼可前往 Github:https://github.com/Krryxa/my-transfer
歡迎 start
呼呼,雙休好好休息了~~
博客地址:https://ainyi.com/63
轉載于:https://www.cnblogs.com/ainyi/p/10125443.html
總結
以上是生活随笔為你收集整理的数据量庞大的分页穿梭框实现的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。