之前写过一个优化部分代码的el-checkbox
这次项目要求el-tree写一个shift选项,基本很多依赖的都是element-ui本身的方法,但是踩了一个坑,就是很简单的坑,以为是别的错误,发现后简直哭笑不得,这个坑来给大家填一下。
写一下前期的我的数据结构之类的,供参考!
我的数据结构是三层,项目只有三层的,所以更深层次的大家可以去找一下,或者在我的基础上加以优化,有更优化的可以私信我奥
1: 数据(因为我的数据是从后端拿过来再处理的我简单码一个结构)
[
{
id:"1",
label: "文字",
children:[
{
id:"1",
label: "文字",
children:[
{
label: "",
value: "",
id: ""
}
2: 了解我的数据结构后我们开始看代码啦
首先我们必须在el-tree上面设置keys, 建议选择还是用keys,避免数据重复出现错误
node-key="id" 很重要
<el-tree
ref="tree"
:data="loadCases"
show-checkbox
:check-on-click-node="true"
node-key="id"
highlight-current
:expand-on-click-node="false"
@check="handleCheckChange"
/>
3: 做好基本工作现在就来写方法吧,使用这个事件获取到属性
4: 这个事件是调用我们的shift事件的把数据抛进去
shiftClick(datas) {
// 获取选中的节点和半选中节点
const AllcheckedNodes = this.$refs.tree.getCheckedNodes(false, true);
// 选中的节点的索引
const chilIndex = AllcheckedNodes.findIndex(item => item.id === datas.id);
// 截取索引1 到 选中的之间的数据
const newAll = AllcheckedNodes.slice(1, chilIndex);
// 反转数据并拿到的第一个就是当前选中的父节点
const parent = newAll.reverse().find(item => item.children);
// 父节点的索引
const parentIndex = AllcheckedNodes.findIndex(item => item.id === parent.id);
// 获取父节点后面的所有数据
const parentAfter = AllcheckedNodes.slice(parentIndex + 1);
// 当前父元素后面的第一个兄弟索引(反正就是后面的元素,有可能是兄弟也有可能是子元素)
const parentTwo = parentAfter.find(item => item.children) || parentAfter[parentAfter.length - 1];
const parentTwoIndex = AllcheckedNodes.findIndex(item => item.id === parentTwo.id);
// 选中的数组,当前父级之下的数组内的
const chekbox = AllcheckedNodes.slice(parentIndex + 1, parentAfter.find(item => item.children) ? parentTwoIndex : parentTwoIndex + 1);
// 这个事件是用来确定第一次按下shift时
this.checkPinClick(datas, { allList: parent.children || [] });
const this_ = this;
setTimeout(() => {
// 筛选出中间值
this.selectionChange(chekbox, { allList: parent.children || [], selectData: chekbox });
setTimeout(() => {
for (let i = 0; i < chekbox.length; i++) {
// 选择
this_.$refs.tree.setChecked(chekbox[i].id, true, false);
}
}, 75);
}, 60);
},
5:下面的代码是shift事件里面的,我还是用了我上次checkbox 的事件,对于不同数据进行了优化
用mixin引入就好了,数据不一致请自行修改哦
export default {
data() {
return {
starNum: -1, // 作为起点
pin: false, // 默认为false
indeterminate: true // checkbox是否可选状态
};
},
watch: {
pin: {
handler(val) {
if (!val) {
this.starNum = -1;
}
}
}
},
mounted() {
// 监听按下键盘事件
window.addEventListener("keydown", e => {
if (e.keyCode === 16 && e.shiftKey) {
this.pin = true;
}
});
window.addEventListener("keyup", e => {
this.pin = false;
});
},
methods: {
// 复选框多选功能
/**
* @param checked 选中的
* @param allList 所有数据
* @param selectData 返回选中的
* @param treeCheck el-tree返回选中的
*/
selectionChange(checked, { allList, selectData }) {
const this_ = this;
setTimeout(() => {
const data = allList; // 获取所有数据
const starNum = this.starNum; // 起点数 从-1开始
const endData = checked[checked.length - 1];
const endIdx = data.findIndex(item => {
if (this.stringFlag(item)) {
if (this.stringFlag(endData)) {
return item === endData;
} else {
return item === endData.label;
}
} else {
if (this.stringFlag(endData)) {
return item.label === endData;
} else {
return item.label === endData.label;
}
}
}); // 终点数
const dataStarNum = this.stringFlag(data[starNum] || "") ? data[starNum] : data[starNum].label;
const arraySome = checked.some(item => {
if (this.stringFlag(item)) {
return item === dataStarNum;
} else {
return item.label === dataStarNum;
}
});
if (this_.pin && arraySome) { // 判断按住
const sum = Math.abs(starNum - endIdx) + 1; // 这里记录终点
const min = Math.min(starNum, endIdx); // 这里记录起点
let i = 0;
while (i < sum) {
const index = min + i;
const dataIndex = this.stringFlag(data[index] || "") ? data[index] : data[index].label;
const flagIdx = selectData.find(item => this.stringFlag(item) ? item === dataIndex : item.label === dataIndex); // 判断区间内的数据是否已选中
if (!flagIdx) { // 值是否选中
selectData.push(this.stringFlag(data[index]) ? dataIndex : data[index]);
}
i++;
}
}
return selectData;
}, 50);
},
// 记录第一次按下shift
checkPinClick(check, { allList }) {
if (this.pin && this.starNum === -1) {
this.starNum = allList.findIndex(item => {
if (typeof (item) === "string") {
if (typeof (check) === "string") {
return item === check;
} else {
return item === check.label;
}
} else {
if (typeof (check) === "string") {
return item.label === check;
} else {
return item.label === check.label;
}
}
}); // 记录起点
}
},
stringFlag(item) {
return typeof (item) === "string";
}
}
};
到这里就OOOOK啦!
大家注意!!!敲黑板!大坑来啦
在el-tree里面有
setCheckedKeys 和 setChecked 两个设置勾选的方法! setCheckedKeys: 通过 keys 设置目前勾选的节点,使用此方法必须设置 node-key 属性, 他的意思就是,他会把你之前的其他的选择全部清除掉(传的是数组) setChecked: 通过 key / data 设置某个节点的勾选状态,使用此方法必须设置 node-key 属性,而这个是设置你所传入的data和keys值的状态,不会清除之前的选中!!!(传的是单个值) 按照自己啊想要的来使用 |
就酱紫啦!!!有甚么更好的方法及的告诉我呦!握爪