今日,在vue项目中使用饿了么的Cascader级联选择器时,遇到了一个问题,情景时这样的, 数据是从后台拿到的,前端要做出的效果是当满足某些条件时,某些选项禁止选中。花了很长时间解决这个问题,于是写这篇文章记录解决方案。
如上图所示,假如 ecs为v类型,则不允许选中其子节点。 按照以往经验,简单分析,应该是树的这个节点添加一个字段就能实现禁用,果不其然,去饿了么官网查看得知(Cascader级联选择器),添加一个disabled属性即可。
于是对后端返回的数据进行如下处理:
getTreeList(val) {
//对 treeList 进行递归操作,禁止选中t和v
val &&
val.forEach(item => {
if (item.type == "t" || item.type == "v") {
item.disabled = true; // 如果类型为t或者v,就增加禁用选项
}
if (item.children) {
this.getTreeList(item.children);
}
});
return val ;
}
如上代码显示,递归遍历treeList ,将所有节点及其子节点进行遍历,判断type属性是否为t或者v ,如果是 就给该节点增加disabled属性,并设置为true, item是一个json对象,里面并没有disabled字段,显式的指定item.disabled=true ,就给该json对象中增加了disabled属性, 并设为true。(一下子暴露了对js中的对象的理解并不是很透彻。。) 。
这样就解决了我的需求, 但是这里仍想记录一下我当时的做法。
for(let elem of val.values()){
if(elem.type=="t"|| elem.type=="v"){
// elem={
// ...elem,
// disabled: true
// };
elem.disabled= true;
}
if(elem.children ){
this.getTreeList(elem.children);
}
}
return val ;
}
注意我注释的部分,使用三元运算符, elem={ ...elem ,disabled:true},原以为没问题,但是检测发现,使用该方式并没用,查下了资料并没有找到原因。希望读完这篇文章的哥们指点一下,在下感激不尽!
附上部分页面代码(有删改,至于为什么你懂。。):
<el-cascader
v-model="pid"
:options="this.treeList"
:props="moduleProps"
change-on-select
ref="cascader"
></el-cascader>
data(){
return (){
moduleProps: {
label: "name",
value: "id",
children: "children"
}
}
},
computed: {
treeList() {
return this.TestController.allTree.data;
} ,
}
另外附上,表单编辑时,级联框回显的解决方案: 官方文档指出,默认值通过数组的方式指定,即我们通过数组方法给出选中节点的所有的父节点,就能回显。回到本例中,原有数据结构是一个tree ,节点下面有子节点,子节点下面还有节点,为了拿到选中节点的父节点,我在定义了一个变量,一维json数组 idAndParent=[] ,然后对原有的数据结构(树)进行遍历, 取出所有的节点id和父节点id(即该节点的parentId),放进这个一维数组,然后在通过选中节点的id,去一维数组中查找该id,进而拿到paretnId 这样通过递归,就能拿到选中节点的所有父节点,在外部定义数组,每次找到父节点,就把它push到该数组中。下面附上代码:
getIdAndParent(tree, idAndParentIds) {// idAndParentIds用来保存所有节点的id,parentId
// 对原有的数据结构进行遍历,拿出所有节点的id,parentId到一个一维数组中。
tree.forEach(item => {
let mid = {
id: item.id,
parentId: item.parentId,
};
idAndParentIds.push(mid);
if (item.children) {
this.getIdAndParent(item.children, idAndParentIds);
}
});
},
getId(id, parentIds, idAndParent) {
idAndParent.forEach(item => {
if (item.id == id) {
parentIds.push(id);
if (item.parentId != -1) {
this.getId(item.parentId, parentIds, idAndParent);
}
}
});
},
// 编辑时 数据回显
editShow() { // idAndParent保存 Tree所有节点的id和parentId
let idAndParent=[];// idAndParent保存 Tree所有节点的id和parentId
this.getIdAndParent(this.treeList,idAndParent);
let parentIds = []; // 用于保存选中节点的父节点及父节点的父节点
this.getId(this.form.parentId, parentIds, idAndParent);
this.parentId = parentIds.reverse(); //反转数组
},
我的级联框绑定的就是parentId ,进行编辑操作时,弹出表单时, 触发editShow(),方法, 从而触发了一系列别的方法,最后完成取到选中节点的所有的父节点,并将其赋值给parentId,完成回显。