级联选择器多选功能时主要用到的函数
1、校验所给层级是否有效并且是否为完整路径
// 功能:涉及到级联选择器回显时,需校验是否为完整的路径,是则回显,不是则无无效路径
// options为级联数据,selectedPaths为要校验的数据
validatePaths(selectedPaths, options) {
let {originKeys} = this;
let current = options;
for (const value of selectedPaths) {
if (!current) return false;
const node = current.find(item => item[originKeys.value] === value);
if (node) {
current = node.children;
} else {
return false;
}
}
// 校验是否为完整路径
return this.isChange ? true : !current || current.length === 0;
},
2、查找元素父级
// 使用场景:如果所有子节点状态变成已选择,那么要找到父级将其状态也变成已选择,应用于回显以及操作节点时使用
// value为操作值,arr为级联数据
findParentByValue(value, arr) {
let {originKeys} = this;
let parent = null;
const findParent = (items, parentObj) => {
for (const item of items) {
if (item[originKeys.value] === value) {
parent = parentObj;
break;
}
if (item.children) {
findParent(item.children, item);
}
}
};
findParent(arr, null);
return parent;
},
3、获取所有级别的路径
getAllLevelsPath() {
let str = '';
let {originKeys} = this;
this.activeAry.forEach((item, index) => {
str +=
index < this.activeAry.length - 1
? item.active[originKeys.label] + this.separator
: item.active[originKeys.label];
});
return str;
},
4、状态判断
// 判断各个项状态,需要根据子项的状态判断父级也需要根据父级状态判断子集
allCheckStatus() {
if (this.options.every(item => !this.getIsNotDisabled(item))) {
return 'disabled'
} else if (this.allCheckTrue(this.options)) {
return 'checked'
} else if (this.hasCheckTrue(this.options)) {
return 'indeterminate'
} else {
return 'unChecked'
}
},
// 元素没有被禁用则返回true
getIsNotDisabled(item) {
let {defaultDisabledItems, originKeys} = this;
if (!this.isChange) {
if (defaultDisabledItems.includes(item[originKeys.value])) {
return false;
}
if (item.children && item.children.length > 0) {
return item.children.some(child => this.getIsNotDisabled(child));
}
return true;
} else {
return !defaultDisabledItems.includes(item[originKeys.value])
}
},
// 多选级联每一项元素的勾选状态
getCheckStatus(item) {
if (!this.isChange) {
if (!this.getIsNotDisabled(item)) {
return 'disabled'
} else if (!item.check &&
(!item.children || !item.children.length || !this.hasCheckTrue(item.children))
) {
return 'unChecked'
} else if (!item.children || !item.children.length || this.allCheckTrue(item.children)) {
return 'checked'
} else {
return 'indeterminate'
}
} else {
return !this.getIsNotDisabled(item) ? 'disabled' : item.check ? 'checked' : 'unChecked'
}
},
// 所有元素是否都被选择,包括孩子元素,剔除禁选元素
allCheckTrue(arr) {
return arr.every(
item => (item.check || !this.getIsNotDisabled(item)) &&
(!item.children || !item.children.length || this.allCheckTrue(item.children)))
},
// 判断孩子元素中是否有被选择的,剔除禁选元素
hasCheckTrue(arr) {
return arr.some(item => item.check &&
this.getIsNotDisabled(item) ||
(item.children && this.hasCheckTrue(item.children))
);
},
5、给初始化的数组增加check属性
addCheckProperty(arr, ids, flag) {
let {originKeys} = this;
for (const item of arr) {
if (ids.includes(item[originKeys.value])) {
this.$set(item, 'check', flag);
this.updataSelectedItems(item, flag)
}
if (item.children && item.children.length) {
this.addCheckProperty(item.children, ids, flag);
}
}
},
6、元素没有被禁用则返回true
// 判断元素有没有被禁用,涉及父级全选以及回显功能
getIsNotDisabled(item) {
let {defaultDisabledKeys, originKeys} = this;
if (!this.isChange) {
if (defaultDisabledKeys.includes(item[originKeys.value])) {
return false;
}
if (item.children && item.children.length > 0) {
return item.children.some(child => this.getIsNotDisabled(child));
}
return true;
} else {
return !defaultDisabledKeys.includes(item[originKeys.value])
}
},
7、更新某一项
updataSelectedItems(item, flag) {
let {originKeys} = this;
this.$set(item, 'check', flag);
if (item.children && item.children.length && !this.isChange){
this.changeCheckProperty(item.children, flag);
} else {
if (flag) {
// 未被禁选&&没有被选择的元素push到selectedItems
this.getIsNotDisabled(item) &&
!this.selectedItems.find(selectedItem => selectedItem[originKeys.value] === item.value) &&
this.selectedItems.push(item)
} else {
// 过滤掉取消勾选的元素
this.selectedItems = this.selectedItems.filter(
val => val[originKeys.value] !== item[originKeys.value]
)
}
// 拿到全路径
if (this.isShowLevels) {
let hierarchyArr = [];
let selectedOptionsArr = []
this.selectedItems.forEach(item => {
hierarchyArr.push(
this.getSelectedOptionsWithPath(item[originKeys.value], this.options).hierarchy
)
selectedOptionsArr.push(
this.getSelectedOptionsWithPath(item[originKeys.value], this.options).selectedOptions
)
})
this.selectedItemsAllPath = hierarchyArr
this.activeItems = selectedOptionsArr
}
}
},
8、返回点击事件回传参数 以及全路径
//事件回传参数处理
getSelectedOptionsWithPath(val, options) {
let {originKeys, separator} = this;
let hierarchy = null;
let selectedOptions = [];
const findOption = (items, parentHierarchy) => {
for (const item of items) {
if (item[originKeys.value] === val) {
let obj = {}
obj[originKeys.value] = item[originKeys.value]
obj[originKeys.label] = item[originKeys.label]
selectedOptions.push(obj);
hierarchy = parentHierarchy ?
`${parentHierarchy}${separator}${item[originKeys.label]}` :
item[originKeys.label];
return true;
}
if (item.children && item.children.length) {
const currentHierarchy = parentHierarchy ?
`${parentHierarchy}${separator}${item[originKeys.label]}` :
item[originKeys.label];
const found = findOption(item.children, currentHierarchy);
if (found) {
let obj = {}
obj[originKeys.value] = item[originKeys.value]
obj[originKeys.label] = item[originKeys.label]
selectedOptions.unshift(obj);
return true;
}
}
}
return false;
};
findOption(options, null);
return {hierarchy, selectedOptions};
},