目录
- 输入式动态添加
- 单选式动态添加
- 组合式动态添加
- 组合式动态添加(回传名称)
- 单选、多选组合式
- 数据回显
- 完整示例
- 总结
- 单选切换多选(补充)
- 下拉框渲染卡顿问题(补充)
- 双循环遍历优化
输入式动态添加
输入式:即input的值由用户输入;例如:通过自定义用户标签,给用户动态添加多个标签。
<template> | |
<div class="app"> | |
<div v-for="item in table" :key="item.id"> | |
<el-input v-model="item.label" class="el-input"></el-input> | |
</div> | |
<el-button @click="addInput">添加</el-button> | |
<el-button @click="search">查看</el-button> | |
</div> | |
</template> | |
<script> | |
export default { | |
data () { | |
return { | |
table: [ | |
{ id: '12121', label: '' } | |
] | |
} | |
}, | |
methods: { | |
// 动态添加 | |
addInput () { | |
this.table.push({ id: Date.now(), label: '' }) | |
}, | |
// 查看 | |
search () { | |
console.log(this.table) | |
}, | |
} | |
} | |
</script> |
单选式动态添加
例如:给一名老师动态添加多个监考科目,后台接收科目代码(courseId)。
<div v-for="(item,index) in list" :key="item.id"> | |
<el-select | |
class="el-select" | |
v-model="item.courseId" | |
placeholder="请选择" | |
@change="changeSelect($event,index)"> | |
<el-option | |
v-for="item in options" | |
:key="item.value" | |
:label="item.label" | |
:value="item.value"> | |
</el-option> | |
</el-select> | |
</div> | |
list: [ | |
{ courseId: '', id: '1' } | |
], | |
options: [ | |
{ value: '123', label: '英语' }, | |
{ value: '456', label: '数学' }, | |
{ value: '868', label: '语文' }, | |
{ value: '672', label: '化学' }, | |
{ value: '684', label: '物理' } | |
], | |
// 动态添加 | |
addInput () { | |
this.list.push({ id: Date.now(), courseId: '' }) | |
}, |
组合式动态添加
例如:给学生各个科目打上分数。
<div v-for="item in list1" :key="item.id"> | |
<el-select | |
class="el-select" | |
v-model="item.courseId" | |
placeholder="请选择科目" | |
> | |
<el-option | |
v-for="item in options" | |
:key="item.value" | |
:label="item.label" | |
:value="item.value"> | |
</el-option> | |
</el-select> | |
<el-input v-model="item.grade" class="el-input" placeholder="请填写分数"></el-input> | |
</div> | |
list1: [ | |
{ courseId: '', id: '1', grade: '' } | |
], | |
options: [ | |
{ value: '123', label: '英语' }, | |
{ value: '456', label: '数学' }, | |
{ value: '868', label: '语文' }, | |
{ value: '672', label: '化学' }, | |
{ value: '684', label: '物理' } | |
], | |
addInput () { | |
this.list1.push({ id: Date.now(), courseId: '', grade: '' }) | |
}, | |
// this.list1 | |
// [ | |
// { | |
// "courseId":"123", | |
// "id":"1", | |
// "grade":"96" | |
// }, | |
// { | |
// "id":1636423648221, | |
// "courseId":"456", | |
// "grade":"100" | |
// } | |
// ] |
组合式动态添加(回传名称)
例如:给学生各个科目打上分数,后端需要同时接收科目名称和科目id。
// 后台接收的数据 | |
courseList:[ | |
{courseId: '', grade: '', courseName: '' } | |
{courseId: '', grade: '', courseName: '' } | |
] |
这时候,只需要给el-select添加change事件,在获取id的同时获取到名称即可。
<div v-for="(item,index) in list2" :key="item.id"> | |
<el-select | |
class="el-select" | |
v-model="item.courseId" | |
placeholder="请选择科目" | |
@change="changeOneCourse($event,index)" | |
> | |
<el-option | |
v-for="item in options" | |
:key="item.value" | |
:label="item.label" | |
:value="item.value"> | |
</el-option> | |
</el-select> | |
<el-input v-model="item.grade" class="el-input" placeholder="请填写分数"></el-input> | |
</div> | |
changeOneCourse(val, index) { | |
this.options.find((item) => { | |
if (item.value === val) { | |
this.list2[index]['courseName'] = item.label // 根据绑定值id获取到名称label | |
} | |
}) | |
} | |
// this.list2: [ | |
// { | |
// "courseId":"123", | |
// "id":"1", | |
// "grade":"96", | |
// "courseName":"英语" | |
// } | |
// ] |
单选、多选组合式
例如:给各个年级添加不同科目,后端需要同时接收【科目名称,科目id】,【年级id,年级名称】。
gradeList:[ | |
{ courseList: [ | |
{ courseId: '', courseName: '' }, | |
{ courseId: '', courseName: '' } | |
], | |
gradeData: { grade: '', gradeName: ' ' } | |
} | |
] | |
<div v-for="(item,index) in list3" :key="item.id"> | |
<el-select v-model="item.gradeList" placeholder="请选择年级" ="changeGrad($event,index)"> | |
<el-option | |
v-for="item in options1" | |
:key="item.value" | |
:label="item.label" | |
:value="item.value"> | |
</el-option> | |
</el-select> | |
<el-select v-model="item.courseList" multiple placeholder="请选择科目" ="changeSelect($event,index)"> | |
<el-option | |
v-for="item in options" | |
:key="item.value" | |
:label="item.label" | |
:value="item.value"> | |
</el-option> | |
</el-select> | |
</div> | |
<el-button "addInput">添加</el-button> | =|
<el-button "search">查看</el-button> | =|
list3: [ | |
{ gradeList: '', id: '1', courseList: '' } | |
], | |
options: [ | |
{ value: '123', label: '英语' }, | |
{ value: '456', label: '数学' }, | |
{ value: '868', label: '语文' }, | |
{ value: '672', label: '化学' }, | |
{ value: '684', label: '物理' } | |
], | |
options1: [ | |
{ value: '1238635', label: '一年级' }, | |
{ value: '4568635', label: '二年级' }, | |
{ value: '8688635', label: '三年级' }, | |
{ value: '6728635', label: '八年级' }, | |
{ value: '6848635', label: '九年级' } | |
], | |
courseList: [], // 存放多选 | |
grade: [], // 存放单选 | |
name: [], | |
methods: { | |
addInput () { | |
this.list3.push({ id: Date.now(), gradeList: '', courseList: '' }) | |
}, | |
search () { | |
let arr3 = [] | |
for (let i = 0; i < this.courseList.length; i++) { | |
arr3.push(Object.assign(this.courseList[i] || {}, this.grade[i] || {})) // 合并数组对象 | |
} | |
console.log(arr3) // 输出传给后台的结构 | |
}, | |
// 处理多选的值 | |
changeSelect (val, index) { | |
let courseList = { courseList: [] } | |
this.name = [] | |
this.courseList[index] = courseList // 初始化第一个值 | |
// =====================根据变化的值赋值,有就赋值,无就删除=========================== | |
for (let i = 0; i <= val.length - 1; i++) { | |
this.options.find((item) => { | |
if (item.value === val[i]) { | |
this.name.push(item.label) // 根据绑定值id获取到名称label | |
} | |
}) | |
} | |
// =====================进行赋值=========================== | |
for (let i = 0; i <= val.length - 1; i++) { | |
let obj = {} | |
obj['courseId'] = val[i] | |
obj['courseName'] = this.name[i] | |
this.courseList[index]['courseList'].push(obj) | |
} | |
console.log(this.courseList) // 相当于多选课程的数据 | |
}, | |
changeGrad (val, index) { | |
this.options1.find((item) => { | |
if (item.value === val) { | |
this.list2[index]['gradeName'] = item.label // 根据绑定值id获取到名称label | |
} | |
}) | |
let grade = { grade: { gradeName: '', gradeId: '' } } | |
// | |
let gradeName = '' | |
this.grade[index] = grade // 初始化第一个值 | |
this.options1.find((item) => { | |
if (item.value === val) { | |
gradeName = item.label // 根据绑定值id获取到名称label | |
} | |
}) | |
// =====================进行赋值=========================== | |
this.grade[index]['grade']['gradeName'] = gradeName | |
this.grade[index]['grade']['gradeId'] = val | |
console.log(this.grade) // 相当于单选年级的数据 | |
} | |
} |
数据回显
动态添加数据之后,数据也正常提交给了后台,往往数据可能还需要编辑或修改,那就会涉及到数据的回显问题。
// 定义一个test方法,和echoData查看回显的数据是否正确 | |
// 数据回显 | |
echoData () { | |
this.isChange = false | |
this.arr3 = this.echoList // arr3提到data中全局保存 | |
let courseList = [] // 保存多选的值 | |
let obj = {} | |
// 回显时初始化单选值(年级) | |
this.grade = this.echoList.map(item => { | |
return { grade: { ...item.grade } } | |
}) | |
// 回显时初始化多选值(课程) | |
for (let key in this.echoList) { | |
let obj = {} | |
obj['courseList'] = this.echoList[key]['courseList'] | |
this.courseList.push(obj) | |
} | |
// 1.拆分后台数据,构造年级回显 | |
this.options1 = this.echoList.map(item => { | |
item.courseList.forEach(val => { | |
courseList.push(val) | |
}) | |
return { | |
value: item.grade['id'], | |
label: item.grade['gradeName'] | |
} | |
}) | |
// 数组对象去重 | |
courseList = courseList.reduce((a, b) => { | |
obj[b.id] ? '' : obj[b.id] = true && a.push(b) | |
return a | |
}, []) | |
// 2.拆分后台数据,构造科目回显 | |
this.options = courseList.map(item => { | |
return { | |
value: item.id, | |
label: item.courseName | |
} | |
}) | |
// 3.拆分后台数据,构造动态绑定的数据回显 | |
this.list3 = this.echoList.map(item => { | |
let course = [] | |
item.courseList.forEach(val => { | |
course.push(val.id) | |
}) | |
return { | |
gradeList: item.grade['id'], | |
courseList: course | |
} | |
}) | |
console.log(this.arr3) | |
}, | |
// 用于检查回显数据的赋值是否正确 | |
test () { | |
this.courseList = [] | |
this.grade = [] | |
// 回显时初始化单选值(年级) | |
this.grade = this.echoList.map(item => { | |
return { grade: { ...item.grade } } | |
}) | |
// 回显时初始化多选值(课程) | |
for (let key in this.echoList) { | |
let obj = {} | |
obj['courseList'] = this.echoList[key]['courseList'] | |
this.courseList.push(obj) | |
} | |
console.log(this.grade) | |
console.log(this.courseList) | |
} |
完整示例
这里暂时不对代码进行优化处理。
<template> | |
<div class="app"> | |
<!--// 输入式--> | |
<!--<div v-for="item in table" :key="item.id">--> | |
<!--<el-input v-model="item.label" class="el-input"></el-input>--> | |
<!--</div>--> | |
<!--单选式--> | |
<!-- <div v-for="item in list" :key="item.id"> | |
<el-select | |
class="el-select" | |
v-model="item.courseId" | |
placeholder="请选择"> | |
<el-option | |
v-for="item in options" | |
:key="item.value" | |
:label="item.label" | |
:value="item.value"> | |
</el-option> | |
</el-select> | |
<el-input v-model="item.grade" class="el-input"></el-input> | |
</div>--> | |
<!--组合式--> | |
<!-- <div v-for="item in list2" :key="item.id"> | |
<el-select | |
class="el-select" | |
v-model="item.courseId" | |
placeholder="请选择科目" | |
> | |
<el-option | |
v-for="item in options" | |
:key="item.value" | |
:label="item.label" | |
:value="item.value"> | |
</el-option> | |
</el-select> | |
<el-input v-model="item.grade" class="el-input" placeholder="请填写分数"></el-input> | |
</div>--> | |
<!--组合式(回显名称)--> | |
<!-- <div v-for="(item,index) in list2" :key="item.id"> | |
<el-select | |
class="el-select" | |
v-model="item.courseId" | |
placeholder="请选择科目" | |
@change="changeOneCourse($event,index)" | |
> | |
<el-option | |
v-for="item in options" | |
:key="item.value" | |
:label="item.label" | |
:value="item.value"> | |
</el-option> | |
</el-select> | |
<el-input v-model="item.grade" class="el-input" placeholder="请填写分数"></el-input> | |
</div>--> | |
<!--单选、多选组合式--> | |
<div v-for="(item,index) in list3" :key="item.id"> | |
<el-select v-model="item.gradeList" placeholder="请选择年级" @change="changeGrad($event,index)"> | |
<el-option | |
v-for="item in options1" | |
:key="item.value" | |
:label="item.label" | |
:value="item.value"> | |
</el-option> | |
</el-select> | |
<el-select v-model="item.courseList" multiple placeholder="请选择科目" @change="changeSelect($event,index)"> | |
<el-option | |
v-for="item in options" | |
:key="item.value" | |
:label="item.label" | |
:value="item.value"> | |
</el-option> | |
</el-select> | |
</div> | |
<el-button @click="addInput">添加</el-button> | |
<el-button @click="search">查看</el-button> | |
<el-button @click="echoData">回显</el-button> | |
<el-button @click="test">测试</el-button> | |
</div> | |
</template> | |
<script> | |
export default { | |
name: 'teacher', | |
data () { | |
return { | |
value1: [], | |
table: [ | |
{ id: '12121', label: '' } | |
], | |
list: [ | |
{ courseId: '', id: '1' } | |
], | |
list1: [ | |
{ courseId: '', id: '1', grade: '' } | |
], | |
list2: [ | |
{ courseId: '', id: '1', grade: '', courseName: '' } | |
], | |
list3: [ | |
{ gradeList: '', id: '1', courseList: '' } | |
], | |
options: [ | |
{ value: '123', label: '英语' }, | |
{ value: '456', label: '数学' }, | |
{ value: '868', label: '语文' }, | |
{ value: '672', label: '化学' }, | |
{ value: '684', label: '物理' } | |
], | |
options1: [ | |
{ value: '1238635', label: '一年级' }, | |
{ value: '4568635', label: '二年级' }, | |
{ value: '8688635', label: '三年级' }, | |
{ value: '6728635', label: '八年级' }, | |
{ value: '6848635', label: '九年级' } | |
], | |
courseList: [], // 存放多选 | |
grade: [], // 存放单选 | |
name: [], | |
gradeList: [], // 分数列表 | |
echoList: [ | |
{ | |
'id': '55cca14cad60430191c0c3840a63b50c', | |
'grade': { | |
'id': 'd3d16e7edcbb4c1fb09759725c956dd4', | |
'gradeName': '二年级' | |
}, | |
'courseList': [ | |
{ | |
'id': '1455377986034917378', | |
'courseName': '地理' | |
}, | |
{ | |
'id': '1455377934050713601', | |
'courseName': '数学' | |
} | |
] | |
}, | |
{ | |
'id': '55cca14cad60430191c0c3840a63b50c', | |
'grade': { | |
'id': 'fe3c385ab7c745a692f2c4b32c0cb2a0', | |
'gradeName': '八年级' | |
}, | |
'courseList': [ | |
{ | |
'id': '1455377934050713601', | |
'courseName': '数学' | |
}, | |
{ | |
'id': '1455377958553837569', | |
'courseName': '历史' | |
} | |
] | |
} | |
], | |
isChange: false, | |
arr3: [] | |
} | |
}, | |
methods: { | |
addInput () { | |
this.table.push({ id: Date.now(), label: '' }) | |
this.list.push({ id: Date.now(), courseId: '' }) | |
this.list1.push({ id: Date.now(), courseId: '', grade: '' }) | |
this.list2.push({ id: Date.now(), courseId: '', grade: '', courseName: '' }) | |
this.list3.push({ id: Date.now(), gradeList: '', courseList: '' }) | |
}, | |
search () { | |
// 根据isChange判断数据是否发生变化,如果没发生变化arr3则为后台返回的数据,说明页面未发生变化 | |
if (this.isChange) { | |
this.arr3 = [] | |
for (let i = 0; i < this.courseList.length; i++) { | |
this.arr3.push(Object.assign(this.courseList[i] || {}, this.grade[i] || {})) // 合并数组对象 | |
} | |
} | |
console.log(this.arr3) // 输出传给后台的结构 | |
}, | |
// 处理多选的值 | |
changeSelect (val, index) { | |
this.isChange = true | |
let courseList = { courseList: [] } | |
this.name = [] | |
this.courseList[index] = courseList // 初始化第一个值 | |
// =====================根据变化的值赋值,有就赋值,无就删除=========================== | |
for (let i = 0; i <= val.length - 1; i++) { | |
this.options.find((item) => { | |
if (item.value === val[i]) { | |
this.name.push(item.label) // 根据绑定值id获取到名称label | |
} | |
}) | |
} | |
// =====================进行赋值=========================== | |
for (let i = 0; i <= val.length - 1; i++) { | |
let obj = {} | |
obj['courseId'] = val[i] | |
obj['courseName'] = this.name[i] | |
this.courseList[index]['courseList'].push(obj) | |
} | |
console.log(this.courseList) // 相当于多选课程的数据 | |
}, | |
// 处理单选的值 | |
// changeOneCourse (val, index) { | |
// this.options.find((item) => { | |
// if (item.value === val) { | |
// this.list2[index]['courseName'] = item.label // 根据绑定值id获取到名称label | |
// } | |
// }) | |
// }, | |
changeGrad (val, index) { | |
this.isChange = true | |
// this.options1.find((item) => { | |
// if (item.value === val) { | |
// this.list2[index]['gradeName'] = item.label // 根据绑定值id获取到名称label | |
// } | |
// }) | |
let grade = { grade: { gradeName: '', gradeId: '' } } | |
let gradeName = '' | |
this.grade[index] = grade // 初始化第一个值 | |
this.options1.find((item) => { | |
if (item.value === val) { | |
gradeName = item.label // 根据绑定值id获取到名称label | |
} | |
}) | |
// =====================进行赋值=========================== | |
this.grade[index]['grade']['gradeName'] = gradeName | |
this.grade[index]['grade']['gradeId'] = val | |
console.log(this.grade) // 相当于单选年级的数据 | |
}, | |
// 数据回显 | |
echoData () { | |
this.isChange = false | |
this.arr3 = this.echoList // arr3提到data中全局保存 | |
let courseList = [] // 保存多选的值 | |
let obj = {} | |
// 回显时初始化单选值(年级) | |
this.grade = this.echoList.map(item => { | |
return { grade: { ...item.grade } } | |
}) | |
// 回显时初始化多选值(课程) | |
for (let key in this.echoList) { | |
let obj = {} | |
obj['courseList'] = this.echoList[key]['courseList'] | |
this.courseList.push(obj) | |
} | |
// 1.拆分后台数据,构造年级回显 | |
this.options1 = this.echoList.map(item => { | |
item.courseList.forEach(val => { | |
courseList.push(val) | |
}) | |
return { | |
value: item.grade['id'], | |
label: item.grade['gradeName'] | |
} | |
}) | |
// 数组对象去重 | |
courseList = courseList.reduce((a, b) => { | |
obj[b.id] ? '' : obj[b.id] = true && a.push(b) | |
return a | |
}, []) | |
// 2.拆分后台数据,构造科目回显 | |
this.options = courseList.map(item => { | |
return { | |
value: item.id, | |
label: item.courseName | |
} | |
}) | |
// 3.拆分后台数据,构造动态绑定的数据回显 | |
this.list3 = this.echoList.map(item => { | |
let course = [] | |
item.courseList.forEach(val => { | |
course.push(val.id) | |
}) | |
return { | |
gradeList: item.grade['id'], | |
courseList: course | |
} | |
}) | |
console.log(this.arr3) | |
}, | |
test () { | |
this.courseList = [] | |
this.grade = [] | |
// 回显时初始化单选值(年级) | |
this.grade = this.echoList.map(item => { | |
return { grade: { ...item.grade } } | |
}) | |
// 回显时初始化多选值(课程) | |
for (let key in this.echoList) { | |
let obj = {} | |
obj['courseList'] = this.echoList[key]['courseList'] | |
this.courseList.push(obj) | |
} | |
console.log(this.grade) | |
console.log(this.courseList) | |
} | |
} | |
} | |
</script> | |
<style lang="scss" scoped> | |
.app{ | |
margin: 50px auto; | |
width: 500px; | |
} | |
.el-input{ | |
margin-bottom: 20px; | |
width: 200px; | |
} | |
.el-select{ | |
margin-bottom: 20px; | |
margin-right: 10px; | |
} | |
</style> |
总结
1、动态添加Input,需要密切关注页面和后台数据的处理,简单的直接绑定v-for的item,复杂的需要根据具体需求,进行调整;
2、获取id的同时利用find()获取名称;
3、纯数组合与数组对象之间的转换、合并,利用循环合自定义obj={}保存对象,并循环输出;
4、数组对象的合并,利用Object.assign(),先合并对象;
5、同时获取名称和id需要在change方法里面,同时进行,根据有值就添加,无值就删除原理;
6、数据回显,要保证数据跟动态添加时的绑定值一致 。
单选切换多选(补充)
当输入框根据条件,既可以单选,又可以多选时,会出现切换模式时,无法清除数据的问题。
<div class="select"> | |
<el-select v-model="grade" placeholder="请选择年级" clearable @change="changeGrade"> | |
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"/> | |
</el-select> | |
<el-select v-if="isShowSelect" v-model="course" placeholder="请选择课程" clearable :multiple="isMultiple === '1'"> | |
<el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" | |
/> | |
</el-select> | |
<script> | |
data () { | |
return { | |
isMultiple: '0', | |
isShowSelect: true, | |
isShow: false, | |
course: '', | |
grade: '', | |
options: [ | |
{ value: '1238635', label: '一年级', isMultiple: '0' }, | |
{ value: '4568635', label: '二年级', isMultiple: '0' }, | |
{ value: '8688635', label: '三年级', isMultiple: '1' }, | |
{ value: '6728635', label: '八年级', isMultiple: '1' }, | |
{ value: '6848635', label: '九年级', isMultiple: '1' } | |
], | |
options1: [ | |
{ value: '123', label: '英语' }, | |
{ value: '456', label: '数学' }, | |
{ value: '868', label: '语文' }, | |
{ value: '672', label: '化学' }, | |
{ value: '684', label: '物理' } | |
] | |
} | |
}, | |
methods: { | |
if (val) { | |
// 改变年级时,判断是否可多选 | |
this.isMultiple = this.options.find(item => item.value === val).isMultiple | |
// 多选时,绑定的是数组,单选绑定的是字符串,出现问题的地方可能是这里 | |
this.isMultiple === '1' ? this.course = [] : this.course = '' | |
} | |
} | |
</script> |
可能是切换模式时,需要重新 v-model,但容器又没有重新渲染导致,因此可以在切换的时候,让容器重新渲染,重新 v-model ,首先给选择课程添加 v-if,,然后观察 isMultiple 的变化,变化时,让课程容器重新渲染即可。
watch: { | |
isMultiple (val) { | |
if (val) { | |
this.isShowSelect = false | |
setTimeout(() => { | |
this.isShowSelect = true | |
}) | |
} | |
} | |
}, |
下拉框渲染卡顿问题(补充)
当渲染的数据量很大时,一次性渲染,会造成页面卡顿,甚至内存溢出现象,一次性渲染超过2000条数据的下拉框,就会出现卡顿现象(小编自测的结果,不一定准确)。解决的方法是:分页,同时支持搜索,那就可以使用 Element 的 Cascader 级联选择器。
<el-cascader | |
filterable | |
ref="cascader" | |
:options="options" | |
:key="dialogData.pushType" | |
:disabled="!(dialogData.pushType)" | |
:props="optionsProps" | |
:placeholder="optionsValue.length>0?optionsValue.map(item=>{return item.label}).join(','):placeholder" | |
:show-all-levels="false" | |
@change="changeOptionValue" | |
v-model="optionsValue" | |
size="mini"> | |
</el-cascader> | |
<el-pagination | |
v-if="managersTotal > 1000 && dialogData.pushType === '03'" | |
@current-change="managersCurrentChange" | |
:page-size="1000" | |
layout="total, prev, pager, next" | |
:total="managersTotal"> | |
</el-pagination> |
既然多数据,那必然需要支持多选。
分页下的多选,在点击下一页的时候,会把上一页选择的数据清空,怎么办呢?
那就把在上页中选择的数据,保存起来,在下一页中,加入渲染中去即可。
// @change 中保存选择的数据 | |
changeOptionValue (val) { | |
this.saveOptionsValue = val; // 保存选择的数据 | |
}, | |
// 在点击下一页时,把上一页选择的数据 push 到渲染中去 | |
managersCurrentChange (val) { | |
const hash = {}; | |
// 每次点击时,把重复数据过滤掉,不然点击一次,就会 push 一次重复数据 | |
this.pushOptionsList = this.saveOptionsValue.reduce(function (prev, cur) { | |
!hash[cur.value] ? hash[cur.value] = prev.push({ label: cur.label, value: { value: cur.value, label: cur.label } }) : ''; | |
return prev; | |
}, []); | |
this.optionsValue = this.saveOptionsValue; | |
this.managersPageNo = val; | |
this.renderData(); // 接口调用,渲染数据 | |
}, | |
renderData(){ | |
....... | |
// 把上一页选择的数据,加到数组最前面 | |
this.pushOptionsList.length !== 0 && this.List.unshift(...this.pushOptionsList); | |
} |
最后,在数据渲染时,要给一个渲染中的提示,最好是全局的,同时禁止用户其他的操作。毕竟数据量多,渲染需要一定的时间,这段时间不能被其他操作影响。
openFullScreen2() { | |
const loading = this.$loading({ | |
lock: true, | |
text: 'Loading', | |
spinner: 'el-icon-loading', | |
background: 'rgba(0, 0, 0, 0.7)' | |
}); | |
setTimeout(() => { | |
loading.close(); | |
}, 2000); | |
} |
当然分页是不太符合页面操作逻辑的,数据多的时候,应该满足模糊搜索,而不是一页页去查,再进行搜索。 查这一步,明显多余,那一步到位的做法是什么呢?element的Select选择器就给我们提供了,远程搜索的功能
<el-select | |
:size="isType? 'medium':'mini'" | |
v-model="optionsValue" | |
multiple | |
filterable | |
remote | |
reserve-keyword | |
placeholder="请输入姓名进行搜索" | |
:remote-method="remoteMethod" | |
loading-text="搜索中..." | |
:loading="loading"> | |
<el-option | |
v-for="item in options" | |
:key="item.value" | |
:label="item.label" | |
:value="item.value"> | |
</el-option> | |
</el-select> | |
<script> | |
// 远程搜索 | |
remoteMethod (query) { | |
if (query !== '') { | |
setTimeout(() => { | |
// 调用接口,模糊查询 | |
}, 200); | |
} else { | |
this.managersList = []; | |
} | |
}, | |
</script> |
注意:当el-select开启多选的时候,size最好是medium以上,不然,有时候会发生页面抖动现象
双循环遍历优化
在拆分后台数据,构造年级回显时,用到了下面所示代码
可以看到使用map()和forEach循环遍历数据,这里双循环的时间复杂度为O(n²),当数据量大的时候,太消耗性能了,因此需要优化一下,
// 1.拆分后台数据,构造年级回显 | |
this.options1 = this.echoList.map(item => { | |
item.courseList.forEach(val => { | |
courseList.push(val) | |
}) | |
return { | |
value: item.grade['id'], | |
label: item.grade['gradeName'] | |
} | |
}) | |
// 优化代码,拆分双层遍历,降低时间复杂度,O(n) | |
this.echoList.map(item => {return item.courseList}).forEach(val =>{ | |
courseList.push(...val) | |
}) | |
this.options1 = echoList.map(item =>{ | |
return { | |
value: item.grade['id'], | |
label: item.grade['gradeName'] | |
} | |
}) |