vue自定義穿梭框支持遠(yuǎn)程滾動加載的實(shí)現(xiàn)方法
*分享一個使用比較久的??
技術(shù)框架公司的選型(老項(xiàng)目):vue2 + iview-ui方案的實(shí)現(xiàn)思路是共性的,展現(xiàn)UI樣式需要你們自定義進(jìn)行更改;因?yàn)閕view是全局注入,基本使用原先的類名進(jìn)行二次創(chuàng)建公共組件,修改基礎(chǔ)js實(shí)現(xiàn)邏輯;
需求分析:實(shí)現(xiàn)遠(yuǎn)程滾動加載數(shù)據(jù)的穿梭框
1、創(chuàng)建自定義穿梭框,分左側(cè)和右側(cè)數(shù)據(jù)
2、依賴后端接口,左側(cè)是左側(cè)數(shù)據(jù),右側(cè)是右側(cè)數(shù)據(jù)
3、定義好出入?yún)?shù),支持回顯內(nèi)容及選中內(nèi)容的去重處理
4、綁定對應(yīng)的v-model數(shù)據(jù)響應(yīng)
5、滾動加載數(shù)據(jù),區(qū)分左右區(qū)域;添加自定義指令進(jìn)行監(jiān)聽
6、滾動加載數(shù)據(jù),不丟失已選中的數(shù)據(jù),或去重已選中數(shù)據(jù)
7、支持左右側(cè)的遠(yuǎn)程搜索功能,左右互不影響,檢索數(shù)據(jù)放組件外部進(jìn)行
1、代碼信息
創(chuàng)建ivu-transfer.vue文件;依賴iviewUI請依據(jù)自己的樣式進(jìn)行拷貝;
1.1 自定義滾動監(jiān)聽指令
/** 遠(yuǎn)程滾動加載 */ import Vue from 'vue' Vue.directive("loadTransfer", { bind(el, binding) { const select_dom = el.querySelectorAll('.ivu-transfer-list .ivu-transfer-list-content'); select_dom.forEach((item, index) => { item.addEventListener('scroll', function () { const height = this.scrollHeight - this.scrollTop - 1 <= this.clientHeight; if (height) { binding.value(index) } }) }) } })
1.2 自定義穿梭框代碼
<template> <div class="ivu-transfer"> <div class="ivu-transfer-list" :style="{ width: listStyle.width, height: listStyle.height }" > <div class="ivu-transfer-list-header"> <Checkbox :value="checkLeftAll" @on-change="handleAllLeftCheck" ></Checkbox> <span class="ivu-transfer-list-header-title">源列表</span> <span class="ivu-transfer-list-header-count"> {{ leftDataSource.length }} </span> </div> <div class="ivu-transfer-list-body"> <div class="ivu-transfer-list-content"> <CheckboxGroup v-model="checkLeftAllGroup"> <Checkbox :key="index" :label="item.value" class="ivu-transfer-list-content-item" v-for="(item, index) in leftDataSource" >{{ item.label + `${item.description ? ` - ${item.description}` : ""}` }}</Checkbox > </CheckboxGroup> <div v-if="!leftDataSource.length" class="ivu-transfer-list-content-not-found" > 列表為空 </div> </div> </div> </div> <div class="ivu-transfer-operation"> <Button size="small" type="primary" icon="ios-arrow-back" @click="handleClickArrowBack" :disabled="!checkRightAllGroup.length" ></Button> <Button size="small" type="primary" icon="ios-arrow-forward" @click="handleClickArrowForward" :disabled="!checkLeftAllGroup.length" ></Button> </div> <div class="ivu-transfer-list" :style="{ width: listStyle.width, height: listStyle.height }" > <div class="ivu-transfer-list-header"> <Checkbox :value="checkRightAll" @on-change="handleAllRightCheck" ></Checkbox> <span class="ivu-transfer-list-header-title">目的列表</span> <span class="ivu-transfer-list-header-count"> {{ rightDataSource.length }} </span> </div> <div class="ivu-transfer-list-body"> <div class="ivu-transfer-list-content"> <CheckboxGroup v-model="checkRightAllGroup"> <Checkbox :key="index" :label="item.value" class="ivu-transfer-list-content-item" v-for="(item, index) in rightDataSource" >{{ item.label + `${item.description ? ` - ${item.description}` : ""}` }} </Checkbox> </CheckboxGroup> <div v-if="!rightDataSource.length" class="ivu-transfer-list-content-not-found" > 列表為空 </div> </div> </div> </div> </div> </template> <script> const methods = { // 點(diǎn)擊左側(cè)全選 handleAllLeftCheck() { this.checkLeftAll = !this.checkLeftAll; if (this.checkLeftAll) { this.checkLeftAllGroup = this.leftDataSource.map(item => item.value); } else { this.checkLeftAllGroup = []; } }, // 點(diǎn)擊右側(cè)全選 handleAllRightCheck() { this.checkRightAll = !this.checkRightAll; if (this.checkRightAll) { this.checkRightAllGroup = this.rightDataSource.map(item => item.value); } else { this.checkRightAllGroup = []; } }, // 點(diǎn)擊向右數(shù)據(jù) handleClickArrowBack() { this.moveCheckedData("left"); }, // 點(diǎn)擊向左數(shù)據(jù) handleClickArrowForward() { this.moveCheckedData("right"); }, moveCheckedData(direction) { const newLeftDataSource = []; const newRightDataSource = []; const dataSource = direction === "left" ? this.rightDataSource : this.leftDataSource; dataSource.forEach(item => { const index = direction === "left" ? this.checkRightAllGroup.indexOf(item.value) : this.checkLeftAllGroup.indexOf(item.value); if (index !== -1) { direction === "left" ? newLeftDataSource.push(item) : newRightDataSource.push(item); } else { direction === "left" ? newRightDataSource.push(item) : newLeftDataSource.push(item); } }); this.leftDataSource = direction === "left" ? [...this.leftDataSource, ...newLeftDataSource] : newLeftDataSource; this.rightDataSource = direction === "left" ? newRightDataSource : [...this.rightDataSource, ...newRightDataSource]; this.checkLeftAll = false; this.checkRightAll = false; this.checkLeftAllGroup = []; this.checkRightAllGroup = []; this.$emit("on-change", this.leftDataSource, this.rightDataSource, direction); }, filterDataMethods() { const rightValues = new Set(this.rightDataSource.map(opt => opt.value)); this.leftDataSource = this.leftDataSource.filter( item => !rightValues.has(item.value) ); this.$nextTick(() => { const leftValues = new Set(this.leftDataSource.map(opt => opt.value)); this.rightDataSource = this.rightDataSource.filter( opt => !leftValues.has(opt.value) ); }); } }; export default { props: { listStyle: { type: Object, default: () => ({ width: "250px", height: "380px" }) }, leftData: { type: Array, require: true, default: () => [] }, rightData: { type: Array, require: true, default: () => [] } }, data() { return { checkLeftAll: false, checkRightAll: false, checkRightAllGroup: [], checkLeftAllGroup: [], leftDataSource: [], rightDataSource: [] }; }, watch: { leftData(newVal) { this.leftDataSource = newVal; this.filterDataMethods(); }, rightData(newVal) { this.rightDataSource = newVal || []; this.filterDataMethods(); } }, mounted() { this.$nextTick(() => { this.$emit("on-change", this.leftDataSource, this.rightDataSource); }) }, methods }; </script> <style lang="less" scoped> .ivu-transfer-list-content-item { width: 100%; margin-left: -0.3em; } .ivu-transfer-list-content-not-found { display: block; } </style>
2、內(nèi)容使用api介紹
1、樹形結(jié)構(gòu)入?yún)ⅲ篸ataSource=[{label: '測試',value: 1, description: '拼接內(nèi)容' }],
2、標(biāo)簽引用:<IvuTransfer :leftData="dataSource" :rightData="targetKeys" @on-change="handleChange" v-loadTransfer="handleLoadMore" />
3、相關(guān)api說明文檔在文章底部
<template> <div class="customSearch"> <Input search clearable v-model="formLeftInput" placeholder="請輸入搜索內(nèi)容" @on-clear="handleOnLeftInput" @on-search="handleOnLeftInput" /> <div style="width: 50px"></div> <Input search clearable v-model="formRightInput" placeholder="請輸入搜索內(nèi)容" @on-clear="handleOnRightInput" @on-search="handleOnRightInput" /> </div> <IvuTransfer :leftData="dataSource" :rightData="targetKeys" @on-change="handleChange" v-loadTransfer="handleLoadMore" /> </template> // 遠(yuǎn)程滾動加載 handleLoadMore(index) { if (index === 0 && this.dataLeftHasMore && !this.isShowLoading) { this.curLeftPage++; this.getLeftMockData(); } if (index === 1 && this.dataRightHasMore && !this.rightLoading) { this.curRightPage++; this.getRightTargetKeys(); } }, // 觸發(fā)選中移動 handleChange(newLeftTargetData, newRightTargetKeys, direction) { this.dataSource = [...newLeftTargetData]; this.targetKeys = [...newRightTargetKeys]; if (direction === "right") { return this.remoteCheckPage(); } if (direction === "left") { return this.remoteRightCheckPage(); } }, getLeftData() {}, getRightData() {}
參數(shù) | 說明 | 類型 | 默認(rèn)值 | 必填項(xiàng) |
---|---|---|---|---|
leftData | [{}]-label,value結(jié)構(gòu) | Array[] | [] | 是 |
rightData | [{}]-label,value結(jié)構(gòu) | Array[] | [] | 是 |
on-change | 數(shù)據(jù)變更觸發(fā) | newLeft,newRight, direction | 無 | 否 |
到此這篇關(guān)于vue自定義穿梭框支持遠(yuǎn)程滾動加載的文章就介紹到這了,更多相關(guān)vue遠(yuǎn)程滾動加載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue中通過屬性綁定為元素綁定style行內(nèi)樣式的實(shí)例代碼
這篇文章主要介紹了Vue中通過屬性綁定為元素綁定style行內(nèi)樣式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-04-04element-plus 下拉框?qū)崿F(xiàn)全選的示例代碼
本文主要介紹了element-plus 下拉框?qū)崿F(xiàn)全選的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-05-05Vue項(xiàng)目自動轉(zhuǎn)換 px 為 rem的實(shí)現(xiàn)方法
這篇文章主要介紹了Vue項(xiàng)目自動轉(zhuǎn)換 px 為 rem的實(shí)現(xiàn)方法,本文是通過一系列的配置后,轉(zhuǎn)換成熱門,具體內(nèi)容詳情大家跟隨小編一起通過本文學(xué)習(xí)吧2018-10-10vue 界面刷新數(shù)據(jù)被清除 localStorage的使用詳解
今天小編就為大家分享一篇vue 界面刷新數(shù)據(jù)被清除 localStorage的使用詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09vue基于session和github-oauth2實(shí)現(xiàn)登錄注冊驗(yàn)證思路詳解
通過 sessionId 可以在 session 表中獲取用戶的信息,此外,還利用 session 表實(shí)現(xiàn)了GitHub 的 OAuth2 第三方登錄,本文講解前端通過簡單的方式實(shí)現(xiàn)一個基本的登錄注冊驗(yàn)證功能,感興趣的朋友跟隨小編一起看看吧2024-08-08