级联选择器多选功能时主要用到的函数
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到selectedItemsthis.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 = hierarchyArrthis.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};
},