需求
1.使用element-ui tree组件展现不同类型的机器人的点位信息
2.选择不同点位信息时会在地图上画出不同的线路
3.一次只能选择一个机器人
4.按照选择的顺序画出不同的线路的起始点和途径点
实现
一、实现不同节点的互斥选择
- 保证tree组件的数据的每一个节点和其对应的父节点有相同的id来区分。如下图
- 使用@check="getCheckedNodes"来判断每次点击的节点是否属于相同的robotId里,如果不同则清空所有节点,并把当前节点设置为选中态
getCheckedNodes(data, item) { // 判断节点是否属于相同的robotId里
if(this.sameFamiliyId !== data.robotId) {
this.sameFamiliyId = data.robotId
this.$refs.tree.setCheckedKeys([]) // 清空所有选择的节点
this.$refs.tree.setCheckedKeys([data.id]) // 将当前选择的节点设置为选中态
}
},
二、按照节点选中的顺序输出对应顺序的数组
3. 记录当前节点的选中状态,虽然element的check-change方法提供了当前节点的状态返回,但是当你选择父节点的时候该方法会被多次促发。
4. 把每次选中的节点push到outArray变量中
5. 当点击父节点的时候,如果父节点是选中的状态就取outArray和父节点所有子节点的差集,然后把差集push到outArray中去
6. 最后的代码如下
<template>
<div>
<div class="fistPageSlidePic">
<el-tree
:data="data"
show-checkbox
default-expand-all
node-key="id"
ref="tree"
highlight-current
@check="getCheckedNodes"
@check-change = "ischecked"
:props="defaultProps">
</el-tree>
</div>
</div>
</template>
<script>
import feedBack from './components/feedBack'
export default {
name: "fistPage",
components: {feedBack},
data() {
return {
outArray: [],
checkedflag: false,
sameFamiliyId: '',
data: [
{
id: 1,
label: '物流机器人',
robotId: "wuliuRobot",
children: [
{
id: 2,
location: [114.0076, 24.890],
label: '大门口1',
robotId: "wuliuRobot",
},
{
id: 3,
location: [114.000, 24.000],
label: '大门口2',
robotId: "wuliuRobot",
},
{
id: 4,
location: [114.1111, 24.1111],
label: '大门口1',
robotId: "wuliuRobot",
},
]
},
{
id: 5,
label: '扫地机器人',
robotId: "saodiRobot",
children: [
{
id: 6,
location: [114.6666, 24.6666],
label: '大门口6',
robotId: "saodiRobot",
},
{
id: 7,
location: [114.7777, 24.7777],
label: '大门口2',
robotId: "saodiRobot",
},
{
id: 8,
location: [114.8888, 24.8888],
label: '大门口1',
robotId: "saodiRobot",
},
]
},
],
defaultProps: {
children: 'children',
label: 'label'
}
};
},
methods: {
ischecked(data, checked, node) {
this.checkedflag = checked // 判断当前节点是否被选中
console.log('this.checkedflag', this.checkedflag, data)
},
getCheckedNodes(data, item) {
if(this.checkedflag) {
if(data.children) {
const diffArray = this.diff(this.outArray, data.children)
this.outArray.push(...diffArray)
}else{
this.outArray.push(data)
}
}else{
if(data.children) {
this.outArray = []
}else{
const tempIndex = this.outArray.findIndex((item)=>{
return item.id === data.id
})
this.outArray.splice(tempIndex,1)
}
}
if(this.sameFamiliyId !== data.robotId) {
this.sameFamiliyId = data.robotId
this.$refs.tree.setCheckedKeys([]) // 清空所有选择的节点
this.outArray = [] // 清空输出数组
if(data.children) {
this.outArray.push(data.children)
}else{
this.outArray.push(data)
}
this.$refs.tree.setCheckedKeys([data.id]) // 将当前选择的节点设置为选中态
}
console.log('最后输出的数组', this.outArray)
},
// 数组的差集
diff(fistArray, secondArray) {
const fistArrayIds = fistArray.map((item)=>{
return item.id
})
const secondArrayIds = secondArray.map((item)=>{
return item.id
})
const tempSecond = secondArray.filter((item)=>{
return !fistArrayIds.includes(item.id)
})
const tempFist = fistArray.filter((item)=>{
return !secondArrayIds.includes(item.id)
})
const resultArray = [...tempFist, ...tempSecond]
console.log('差值数组', resultArray)
return resultArray
}
},
};
</script>
<style lang="less" scoped>
.fistPageSlidePic,
.aboutUs {
height: 700px;
width: 100%;
// border: 1px solid red;
}
.fixbar {
// color: red;
position: fixed;
top: 50vh;
right: 50px;
z-index: 100;
}
</style>
三、使用lodash提供的api实现求对象数组的差集
先需要了解lodash的几个关于数组的api
1.求数组的并集 _.union
2.求数组的交集 _.intersection
3.求数组的补集 _.xor
4.数组去重复 _.uniqWith
总之:在并集中求交集的补集就是差集
diffrentArray(fistArray, secondArray) {
const fistIds = fistArray.map((item)=>{
return item.id
})
const secondIds = secondArray.map((item)=>{
return item.id
})
const unionTemp = _.union(fistIds, secondIds) // 求数组的并集
const interTemp = _.intersection(fistIds, secondIds) // 求数组的交集
const xorTemp = _.xor(unionTemp, interTemp) // 在并集中求交集的补集就是差集
const totalArray = _.uniqWith([...fistArray, ...secondArray], _.isEqual)// 数组合并并且去重
const result = totalArray.filter((item)=>{
return xorTemp.includes(item.id)
})
console.log('数组差集 result', result)
}
四、使用Es6的api实现求对象数组的差集
// 数组的差集
diff(fistArray, secondArray) {
const fistArrayIds = fistArray.map((item)=>{
return item.id
})
const secondArrayIds = secondArray.map((item)=>{
return item.id
})
const tempSecond = secondArray.filter((item)=>{
return !fistArrayIds.includes(item.id)
})
const tempFist = fistArray.filter((item)=>{
return !secondArrayIds.includes(item.id)
})
const resultArray = [...tempFist, ...tempSecond]
console.log('差值数组', resultArray)
return resultArray
}
补:用loadas加reduce实现数组的差集(支持多个数组)
diffArray1(...args) {
let total = args[0]
const xorTemp = args.reduce((pre, curren)=>{
total = _.uniqWith([...total, ...curren], _.isEqual) // 数组合并并且去重
return _.intersection(pre, curren) // 求数组的交集
})
return _.xor(total, xorTemp) // 在并集中求交集的补集就是差集
}
reduce函数的使用:
- 该函数会循环数组的每一项去执行一个函数,并且把执行的结果返回
- 该函数可以设置初始值,更神奇的是初始值的类型可以自定义。
举个栗子(统计个字符串中的字母出现的次数),大家好好感受:
totalTitle(title) {
var res = title.split('').reduce((pre, curren)=>{
pre[curren]? pre[curren]++ : pre[curren] = 1
return pre
},{})
console.log('res======>', res)
}
totalTitle('sssssdfdfdfdf') // ===> {s: 5, d: 4, f: 4}