分享-2023年資深前端進階:前端登頂之巔-最全面的前端知識點梳理總結,前端之巔
*分享一個使用比較久的🪜
技術框架公司的選型(老項目):vue2 + iview-ui
方案的實現思路是共性的,展現UI樣式需要你們自定義進行更改;因為iview是全局注入,基本使用原先的類名進行二次創建公共組件,修改基礎js實現邏輯;
需求分析:實現遠程滾動加載數據的穿梭框
1、創建自定義穿梭框,分左側和右側數據
2、依賴后端接口,左側是左側數據,右側是右側數據
3、定義好出入參數,支持回顯內容及選中內容的去重處理
4、綁定對應的v-model數據響應
5、滾動加載數據,區分左右區域;添加自定義指令進行監聽
6、滾動加載數據,不丟失已選中的數據,或去重已選中數據
7、支持左右側的遠程搜索功能,左右互不影響,檢索數據放組件外部進行
1、代碼信息
創建ivu-transfer.vue文件;依賴iviewUI請依據自己的樣式進行拷貝;
1.1 自定義滾動監聽指令
/** 遠程滾動加載 */
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"><divclass="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><divv-if="!leftDataSource.length"class="ivu-transfer-list-content-not-found">列表為空</div></div></div></div><div class="ivu-transfer-operation"><Buttonsize="small"type="primary"icon="ios-arrow-back"@click="handleClickArrowBack":disabled="!checkRightAllGroup.length"></Button><Buttonsize="small"type="primary"icon="ios-arrow-forward"@click="handleClickArrowForward":disabled="!checkLeftAllGroup.length"></Button></div><divclass="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><divv-if="!rightDataSource.length"class="ivu-transfer-list-content-not-found">列表為空</div></div></div></div></div>
</template><script>
const methods = {// 點擊左側全選handleAllLeftCheck() {this.checkLeftAll = !this.checkLeftAll;if (this.checkLeftAll) {this.checkLeftAllGroup = this.leftDataSource.map(item => item.value);} else {this.checkLeftAllGroup = [];}},// 點擊右側全選handleAllRightCheck() {this.checkRightAll = !this.checkRightAll;if (this.checkRightAll) {this.checkRightAllGroup = this.rightDataSource.map(item => item.value);} else {this.checkRightAllGroup = [];}},// 點擊向右數據handleClickArrowBack() {this.moveCheckedData("left");},// 點擊向左數據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、內容使用api介紹
1、樹形結構入參:
dataSource=[{label: '測試',value: 1, description: '拼接內容' }]
,
2、標簽引用:<IvuTransfer :leftData="dataSource" :rightData="targetKeys" @on-change="handleChange" v-loadTransfer="handleLoadMore" />
3、相關api說明文檔在文章底部
<template><div class="customSearch"><Inputsearchclearablev-model="formLeftInput"placeholder="請輸入搜索內容"@on-clear="handleOnLeftInput"@on-search="handleOnLeftInput"/><div style="width: 50px"></div><Inputsearchclearablev-model="formRightInput"placeholder="請輸入搜索內容"@on-clear="handleOnRightInput"@on-search="handleOnRightInput"/></div><IvuTransfer:leftData="dataSource":rightData="targetKeys"@on-change="handleChange"v-loadTransfer="handleLoadMore"/></template>
// 遠程滾動加載handleLoadMore(index) {if (index === 0 && this.dataLeftHasMore && !this.isShowLoading) {this.curLeftPage++;this.getLeftMockData();}if (index === 1 && this.dataRightHasMore && !this.rightLoading) {this.curRightPage++;this.getRightTargetKeys();}},// 觸發選中移動handleChange(newLeftTargetData, newRightTargetKeys, direction) {this.dataSource = [...newLeftTargetData];this.targetKeys = [...newRightTargetKeys];if (direction === "right") {return this.remoteCheckPage();}if (direction === "left") {return this.remoteRightCheckPage();}},getLeftData() {},
getRightData() {}
參數 | 說明 | 類型 | 默認值 | 必填項 |
---|---|---|---|---|
leftData | [{}]-label,value結構 | Array[] | [] | 是 |
rightData | [{}]-label,value結構 | Array[] | [] | 是 |
on-change | 數據變更觸發 | newLeft,newRight, direction | 無 | 否 |