1.采用checkbox实现的穿梭框案例
思路:采用增加变量selected来操作数据
代码:
<template>
<div class="transfer">
<div class="source">
<h3>Source</h3>
<el-input type="text" v-model="sourceSearch" placeholder="Search Source" />
<ul>
<li v-for="item in filteredSourceList" :key="item.key" @click="selectItem(item, 'source')">
<el-checkbox v-model="item.selected" @change="change(item)">{{ item.label }}</el-checkbox>
<!-- <input type="checkbox" v-model="item.selected" />
{{ item.label }} -->
</li>
<li v-if="filteredSourceList.length === 0 && sourceSearch.length > 0">No results found.</li>
</ul>
</div>
<div class="actions">
<el-button @click="moveToTarget">>></el-button>
<el-button @click="moveToSource"><<</el-button>
</div>
<div class="target">
<h3>Target</h3>
<el-input type="text" v-model="targetSearch" placeholder="Search Target" />
<ul>
<li v-for="item in filteredTargetList" :key="item.key" @click="selectItem(item, 'target')">
<!-- <input type="checkbox" v-model="item.selected" />
{{ item.label }} -->
<el-checkbox v-model="item.selected" @change="change(item)">{{ item.label }}</el-checkbox>
</li>
<li v-if="filteredTargetList.length === 0 && targetSearch.length > 0">No results found.</li>
</ul>
</div>
</div>
</template>
<script>
export default {
data() {
return {
sourceList: [
{ key: 1, label: 'Option 1', selected: false },
{ key: 2, label: 'Option 2', selected: false },
{ key: 3, label: 'Option 3', selected: false },
{ key: 4, label: 'Option 4', selected: false },
],
targetList: [],
sourceSearch: '',
targetSearch: '',
};
},
computed: {
filteredSourceList() {
return this.sourceList.filter(item => item.label.toLowerCase().includes(this.sourceSearch.toLowerCase()));
},
filteredTargetList() {
return this.targetList.filter(item => item.label.toLowerCase().includes(this.targetSearch.toLowerCase()));
},
},
methods: {
change(val) {
val.selected = !val.selected;
},
selectItem(item, listType) {
item.selected = !item.selected;
if (listType === 'source') {
this.sourceList = [...this.sourceList];
} else if (listType === 'target') {
this.targetList = [...this.targetList];
}
},
moveToTarget() {
for (let i = this.sourceList.length - 1; i >= 0; i--) {
const item = this.sourceList[i];
if (item.selected) {
this.sourceList.splice(i, 1);
this.targetList.push(item);
item.selected = false;
}
}
},
moveToSource() {
for (let i = this.targetList.length - 1; i >= 0; i--) {
const item = this.targetList[i];
if (item.selected) {
this.targetList.splice(i, 1);
this.sourceList.push(item);
item.selected = false;
}
}
},
},
};
</script>
<style>
.transfer {
display: flex;
justify-content: center;
align-items: center;
}
.source,
.target {
margin: 0 20px;
border: 1px solid pink;
}
.actions {
display: flex;
flex-direction: column;
align-items: center;
margin: 0 10px;
}
ul {
list-style-type: none;
padding: 0;
height: 400px;
}
li {
cursor: pointer;
padding: 5px;
display: flex;
align-items: center;
}
li.selected {
background-color: #eee;
}
button {
margin: 5px 0;
}
</style>
2.采用table实现穿梭框案例
代码:
<template>
<div class="transfer">
<div class="source">
<h3>Source</h3>
<el-input type="text" v-model="sourceSearch" placeholder="Search Source" />
<div v-if="filteredSourceList.length" style="width: 100%; height: 300px">
<el-table
ref="multipleTable"
:data="filteredSourceList"
style="width: 100%"
@selection-change="handleSourceSelectionChange"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column prop="label" label="姓名"> </el-table-column>
</el-table>
</div>
<div v-if="filteredSourceList.length === 0 && sourceSearch.length > 0">No results found.</div>
</div>
<div class="actions">
<el-button @click="moveToTarget">>></el-button>
<el-button @click="moveToSource"><<</el-button>
</div>
<div class="target">
<h3>Target</h3>
<el-input type="text" v-model="targetSearch" placeholder="Search Target" />
<div v-if="filteredTargetList.length" style="width: 100%; height: 300px">
<el-table
v-if="filteredTargetList.length"
:data="filteredTargetList"
style="width: 100%"
@selection-change="handleTargetSelectionChange"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column prop="label" label="姓名"> </el-table-column>
</el-table>
</div>
<div v-if="filteredTargetList.length === 0 && sourceSearch.length > 0">No results found.</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
sourceList: [
{ key: 1, label: 'Option 1' },
{ key: 2, label: 'Option 2' },
{ key: 3, label: 'Option 3' },
{ key: 4, label: 'Option 4' },
],
targetList: [],
sourceSearch: '',
targetSearch: '',
selectSourceList: [],
selectTargetList: [],
};
},
computed: {
filteredSourceList() {
return this.sourceList.filter(item => item.label.toLowerCase().includes(this.sourceSearch.toLowerCase()));
},
filteredTargetList() {
return this.targetList.filter(item => item.label.toLowerCase().includes(this.targetSearch.toLowerCase()));
},
},
methods: {
handleSourceSelectionChange(val) {
this.selectSourceList = [...val];
},
handleTargetSelectionChange(val) {
this.selectTargetList = [...val];
},
moveToTarget() {
for (let i = this.sourceList.length - 1; i >= 0; i--) {
const item = this.sourceList[i];
for (let index = 0; index < this.selectSourceList.length; index++) {
const element = this.selectSourceList[index];
if (item.key == element.key) {
this.sourceList.splice(i, 1);
this.targetList.push(item);
}
}
}
},
moveToSource() {
for (let i = this.targetList.length - 1; i >= 0; i--) {
const item = this.targetList[i];
for (let index = 0; index < this.selectTargetList.length; index++) {
const element = this.selectTargetList[index];
if (item.key == element.key) {
this.targetList.splice(i, 1);
this.sourceList.push(item);
}
}
}
},
},
};
</script>
<style>
.transfer {
display: flex;
justify-content: center;
align-items: center;
}
.source,
.target {
margin: 0 20px;
border: 1px solid pink;
}
.actions {
display: flex;
flex-direction: column;
align-items: center;
margin: 0 10px;
}
ul {
list-style-type: none;
padding: 0;
height: 400px;
}
li {
cursor: pointer;
padding: 5px;
display: flex;
align-items: center;
}
li.selected {
background-color: #eee;
}
button {
margin: 5px 0;
}
</style>
3.不规则穿梭框,采用table+checkbox混合穿梭案例
思路:table我们直接采用select出来的数据,但是右侧的checkbox我们采用字段selected来控制
代码:
<template>
<div class="transfer">
<div class="source">
<h3>Source</h3>
<el-input type="text" v-model="sourceSearch" placeholder="Search Source" />
<div v-if="filteredSourceList.length" style="width: 100%; height: 300px">
<el-table
ref="multipleTable"
:data="filteredSourceList"
style="width: 100%"
@selection-change="handleSourceSelectionChange"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column prop="label" label="姓名"> </el-table-column>
</el-table>
</div>
<div v-if="filteredSourceList.length === 0 && sourceSearch.length > 0">No results found.</div>
</div>
<div class="actions">
<el-button @click="moveToTarget">>></el-button>
<el-button @click="moveToSource"><<</el-button>
</div>
<div class="target">
<h3>Target</h3>
<el-input type="text" v-model="targetSearch" placeholder="Search Target" />
<ul>
<li v-for="item in filteredTargetList" :key="item.key">
<el-checkbox v-model="item.selected">{{ item.label }}</el-checkbox>
</li>
<li v-if="filteredTargetList.length === 0 && targetSearch.length > 0">No results found.</li>
</ul>
</div>
</div>
</template>
<script>
export default {
data() {
return {
sourceList: [
{ key: 1, label: 'Option 1', selected: false },
{ key: 2, label: 'Option 2', selected: false },
{ key: 3, label: 'Option 3', selected: false },
{ key: 4, label: 'Option 4', selected: false },
],
targetList: [],
sourceSearch: '',
targetSearch: '',
selectSourceList: [],
selectTargetList: [],
};
},
computed: {
filteredSourceList() {
return this.sourceList.filter(item => item.label.toLowerCase().includes(this.sourceSearch.toLowerCase()));
},
filteredTargetList() {
return this.targetList.filter(item => item.label.toLowerCase().includes(this.targetSearch.toLowerCase()));
},
},
methods: {
handleSourceSelectionChange(val) {
this.selectSourceList = [...val];
},
moveToTarget() {
for (let i = this.sourceList.length - 1; i >= 0; i--) {
const item = this.sourceList[i];
for (let index = 0; index < this.selectSourceList.length; index++) {
const element = this.selectSourceList[index];
if (item.key == element.key) {
this.sourceList.splice(i, 1);
this.targetList.push(item);
}
}
}
},
moveToSource() {
for (let i = this.targetList.length - 1; i >= 0; i--) {
const item = this.targetList[i];
if (item.selected) {
this.targetList.splice(i, 1);
this.sourceList.push(item);
item.selected = false;
}
}
},
},
};
</script>
<style>
.transfer {
display: flex;
justify-content: center;
align-items: center;
}
.source,
.target {
margin: 0 20px;
border: 1px solid pink;
}
.actions {
display: flex;
flex-direction: column;
align-items: center;
margin: 0 10px;
}
ul {
list-style-type: none;
padding: 0;
height: 300px;
}
li {
cursor: pointer;
padding: 5px;
display: flex;
align-items: center;
}
li.selected {
background-color: #eee;
}
button {
margin: 5px 0;
}
</style>
4.采用table实现的穿梭框带分页系列
思路:在切换分页的时候,要依据对应的左右侧数据将渲染数据从列表移除。比如:左侧切换分页,要将右侧target的list判断一下,是否有数据在当前source页,如果有,讲数据过滤,在进行渲染