通过查找资料将elementui组件增加了部分功能
1、分页(注意分页使用的是先查询出全部数据,再使用js进行算法分页,因为如果一次渲染数据过多,穿梭框加载会有延迟,不太友好)
2、左侧勾选并穿梭后,整个分页相关内容自动更新
3、增加自定义搜索框和筛选策略
4、右侧栏增加了最大数量限制
子组件:
<template>
<!-- 创建模块 -->
<Modal v-model="isShow" @on-cancel="cancle" title="创建自定义模块" width="720">
<Row>
<Col span="4" style="height: 32px; line-height: 32px;">
<Code>*</Code> <span class="model_name_tip">模块名称</span>
</Col>
<Col span="20">
<Input v-model="model_name" maxlength="8" show-word-limit placeholder="输入模块名称(最多输入8个字" />
</Col>
</Row>
<Row style="padding-top: 20px;">
<Col span="12">
<el-input placeholder="请输入搜索关键字" v-model="keyword" class="input-with-select" size="small">
<el-button slot="append" icon="el-icon-search" @click="filterChange"></el-button>
</el-input>
</Col>
</Row>
<Row>
<el-transfer
target-order="unshift"
v-model="formDatas.river"
@change="transferChange"
@left-check-change="leftCheckChange"
:titles="['可选列表', '已选中']"
:data="currentPageDatas"
:format="{noChecked: '${total}',hasChecked: '${checked}/${total}'}"
class="el-transfer_cus" >
<el-pagination
small
slot="left-footer"
align="right"
@current-change="handleCurrentChange"
:current-page="page.pageNo"
:page-size="page.pageSize"
:total="page.total"
:pager-count="5"
layout="prev, pager, next"
></el-pagination>
</el-transfer>
</Row>
</Modal>
<div slot="footer">
<!-- 有表单提交,需要验证输入,所以使用自定底部按钮 -->
<Button type="text" @click="cancle">取消</Button>
<Button type="primary" @click="submitData">确定</Button>
</div>
</template>
<script>
export default {
data(){
return {
isShow:this.attrShow,
model_name:"",
currentPageDatas: [], // 当前页数据
currentDatas: [], // 当前数据
sourceDatas: [], // 源数据,用于临时筛选数据
currentChecks:[], // 左侧框当前已勾选的键数组
page: { pageNo: 1, pageSize: 30, total: 0 },
formDatas:{
river:[] // 已勾选数据
},
numTotal:30, // 最多只能选渠30个
keyword:'' // 搜索关键字
}
},
created() {
this.init()
},
props:{
attrShow:{
type:Boolean,
default:false
}
},
methods:{
// 关闭对话框
cancle(){
this.$emit("updateStatusData",false)
},
// 提交数据
submitData(){
},
// 提交成功时清空数据
clearData(){
this.formDatas.river = []
this.model_name = ""
this.keyword = ""
this.page.pageNo=1
},
// 初始化数据
init() {
let listData = [
{id:1,name:"你好1"},
{id:2,name:"你好2"},
{id:3,name:"你好3"},
]
// 处理字段别名
var currentDatas = listData.map((value, index) => {
return {
label: value.name,
key: value.id,
obj: value,
};
});
// 总数
let arrLength = currentDatas.length;
this.page.total = arrLength;
// 初始化数据
this.currentDatas = currentDatas;
this.sourceDatas = currentDatas;
// 初始化20条数据给当前第一页的变量
this.currentPageDatas = this.currentDatas.slice(0, this.page.pageSize);
},
// 分页change
handleCurrentChange(page_cur) {
this.page.pageNo = page_cur
// 先将选中的从当前数据过滤掉
this.currentDatas = this.currentDatas.filter(
function (value) {
return !this.formDatas.river.includes(value.key);
}.bind(this)
);
// 再将过滤好的当前数据选出指定页
this.currentPageDatas = this.groupFunc(page_cur);
// 再将选中的目标数组补给当前页变量,从而保证之前选的数据能在右边显示
this.currentPageDatas = this.currentPageDatas.concat(
this.sourceDatas.filter(
function (val) {
return this.formDatas.river.includes(val.key);
}.bind(this)
)
);
},
// 监听勾选的数组
leftCheckChange(checks,nochecks){
this.currentChecks = checks
},
// 穿梭change
transferChange(current, direction, move) {
// 为了保证数据的一致性,目标数组还回来之后要插进当前数据变量
if (direction == "left") {
this.currentDatas = this.sourceDatas.filter(
function (val) {
return !current.includes(val.key);
}.bind(this)
);
let arrLength = this.currentDatas.length;
this.page.total = arrLength
} else {
if(this.formDatas.river.length > this.numTotal){
this.$message({
showClose: true,
message: '抱歉,自定义模块游戏不能超过30个',
type: 'warning'
});
this.formDatas.river = this.formDatas.river.filter(
function (val){
return !this.currentChecks.includes(val)
}.bind(this)
)
return
}
}
this.handleCurrentChange(this.page.pageNo)
},
// 穿梭搜索
filterChange() {
// 自定义搜索,从当前数组变量中过滤,再渲染回组件
var currentDatas = this.sourceDatas.filter(
function (val) {
return (
val.obj.name.indexOf(this.keyword) > -1 &&
!this.formDatas.river.includes(val.key)
);
}.bind(this)
);
if (currentDatas.length != this.currentDatas.length) {
this.currentDatas = currentDatas;
this.handleCurrentChange(1);
}
},
// 数组分页函数,返回当前页数据
groupFunc(page_cur) {
var currentDatas = [];
let arrLength = this.currentDatas.length;
if(arrLength <=0){
return []
}
this.page.total = arrLength;
let num = this.page.pageSize;
let pageTotal = 1;
// 最后一页全部勾选时
let total = arrLength / num
if(arrLength % num === 0){
pageTotal = total
} else {
pageTotal = total + 1
}
if(page_cur > pageTotal){
page_cur = pageTotal
}
let index = 0;
for (let i = 0; i < arrLength; i++) {
if (i % num === 0 && i !== 0) {
currentDatas.push(this.currentDatas.slice(index, i));
index = i;
}
if (i + 1 === arrLength) {
currentDatas.push(this.currentDatas.slice(index, i + 1));
}
}
return currentDatas[page_cur - 1];
}
},
watch:{
// 监听对话框状态变化
attrShow:function(){
this.isShow = this.attrShow
},
keyword:function(){
this.filterChange()
}
}
}
</script>
<style>
.model_name_tip{
font-size: 14px;
font-weight: 700;
}
.input-with-select {
background-color: #fff;
width: 284px;
}
.input-with-select .el-input-group__append{
padding: 0px 10px;
}
.input-with-select .el-input__inner{
border: 1px solid #DCDFE6 !important;
}
.el-transfer_cus{
width: 720px;
}
.el-transfer_cus .el-transfer__buttons{
width: 120px !important;
}
.el-transfer_cus .el-transfer__buttons :nth-child(2){
margin-left: 0px !important;
}
.el-transfer_cus .el-transfer-panel {
width: 284px;
height: 450px;
}
.el-transfer_cus .el-transfer-panel__list{
height: 450px;
}
</style>
主组件:
<template>
<div class="moduleCompile">
<div class="moduleCompile_title">
模块编辑
</div>
<div class="moduleCompile_content">
<div class="content_leftBox">
左边模块
</div>
<div class="content_rightBox">
<div class="module_btn">
<el-button @click="addModelShow" size="mini">+ APP模块</el-button>
</div>
</div>
</div>
<addModel :attrShow="addShow" @updateStatusData="updateStatusData"></addModel>
</div>
</template>
<script>
import addModel from './addModel'
export default {
components:{
addModel
},
data(){
return{
addShow:false
}
},
methods:{
// 显示添加框
addModelShow(){
this.addShow = true
},
// 绑定状态更改,子组件通过$emit传入参数
updateStatusData(e){
this.addShow = e
}
}
}
</script>
<style lang="less" scoped>
.moduleCompile_title{
font-size: 18px;
font-weight: 600;
background-color: #e1e1e186;
text-align: left;
padding: 10px 19px;
}
.moduleCompile_content{
// padding:0 20px;
display: flex;
height:calc(100vh - 100px);
.content_leftBox{
width: 20%;
background-color: burlywood;
}
.content_rightBox{
width: 80%;
// background-color: rgba(100, 148, 237, 0.288);
display: flex;
padding: 20px 35px;
.content_nav{
width: 82%;
}
}
}
</style>
最终效果:
组件库:iview + elementui