Javascript 如果选择了子节点,则更新父节点-从子节点到父节点的树遍历

Javascript 如果选择了子节点,则更新父节点-从子节点到父节点的树遍历,javascript,arrays,tree,treeview,Javascript,Arrays,Tree,Treeview,如果选择了任何一个子节点,我希望选择所有父节点。因此,如果任何childnode选中true,我需要将parent(直到root)childSelected属性设置为true var tree = [{ value: "A", checked: false, childSelected: false, children: [{ value: "AA", checked: false, childSelected: false, children:

如果选择了任何一个子节点,我希望选择所有父节点。因此,如果任何childnode
选中
true,我需要将parent(直到root)
childSelected
属性设置为true

var tree = [{
  value: "A",
  checked: false,
  childSelected: false,
  children: [{
    value: "AA",
    checked: false,
    childSelected: false,
    children: [],
    parent: "A"
  }, {
    value: "AB",
    checked: false,
    childSelected: false,
    children: [{
      value: "ABA",
      checked: false,
      childSelected: false,
      children: [{
        value: "ABAA",
        checked: false,
        childSelected: false,
        children: [],
        parent: "ABA"
      }, {
        value: "ABAB",
        checked: false,
        childSelected: false,
        children: [],
        parent: "ABA"
      }, {
        value: "ABAC",
        checked: true,
        childSelected: false,
        children: [],
        parent: "ABA"
      }, {
        value: "ABAD",
        checked: false,
        childSelected: false,
        children: [],
        parent: "ABA"
      }],
      parent: "AB"
    }],
    parent: "A"
  }, {
    value: "AC",
    checked: false,
    childSelected: false,
    children: [{
    value: "ACA",
    checked: false,
    childSelected: false,
    children: [],
    parent: "AC"
  }],
    parent: "A"
  }, {
    value: "AD",
    checked: false,
    childSelected: false,
    children: [],
    parent: "A"
  }],
  parent: null
}]
预期产量

var tree = [{
  value: "A",
  checked: false,
  childSelected: true,
  children: [{
    value: "AA",
    checked: false,
    childSelected: false,
    children: [],
    parent: "A"
  }, {
    value: "AB",
    checked: false,
    childSelected: true,
    children: [{
      value: "ABA",
      checked: false,
      childSelected: false,
      children: [{
        value: "ABAA",
        checked: false,
        childSelected: false,
        children: [],
        parent: "ABA"
      }, {
        value: "ABAB",
        checked: false,
        childSelected: false,
        children: [],
        parent: "ABA"
      }, {
        value: "ABAC",
        checked: true,
        childSelected: false,
        children: [],
        parent: "ABA"
      }, {
        value: "ABAD",
        checked: false,
        childSelected: false,
        children: [],
        parent: "ABA"
      }],
      parent: "AB"
    }],
    parent: "A"
  }, {
    value: "AC",
    checked: false,
    childSelected: false,
    children: [{
    value: "ACA",
    checked: false,
    childSelected: false,
    children: [],
    parent: "AC"
  }],
    parent: "A"
  }, {
    value: "AD",
    checked: false,
    childSelected: false,
    children: [],
    parent: "A"
  }],
  parent: null
}]
let isChecked = obj => {
    return obj.checked || obj.children.some(x => isChecked(x));
};

let setChildSelected = obj => {
    let childSelected = obj.children.length > 0 && isChecked(obj);
    obj.children = obj.children.map(setChildSelected);
    return { ...obj, childSelected };
};

console.log(tree.map(setChildSelected));
这就是我到目前为止所尝试的

var tree = [{
      value: "A",
      checked: false,
      childSelected: false,
      children: [{
        value: "AA",
        checked: false,
        childSelected: false,
        children: [],
        parent: "A"
      }, {
        value: "AB",
        checked: false,
        childSelected: false,
        children: [{
          value: "ABA",
          checked: false,
          childSelected: false,
          children: [{
            value: "ABAA",
            checked: false,
            childSelected: false,
            children: [],
            parent: "ABA"
          }, {
            value: "ABAB",
            checked: false,
            childSelected: false,
            children: [],
            parent: "ABA"
          }, {
            value: "ABAC",
            checked: true,
            childSelected: false,
            children: [],
            parent: "ABA"
          }, {
            value: "ABAD",
            checked: false,
            childSelected: false,
            children: [],
            parent: "ABA"
          }],
          parent: "AB"
        }],
        parent: "A"
      }, {
        value: "AC",
        checked: false,
        childSelected: false,
        children: [{
        value: "ACA",
        checked: false,
        childSelected: false,
        children: [],
        parent: "AC"
      }],
        parent: "A"
      }, {
        value: "AD",
        checked: false,
        childSelected: false,
        children: [],
        parent: "A"
      }],
      parent: null
    }]

class checkbox{
    constructor() {
        this.checkboxTree = tree;
    this.arrayPath = [];
  }

  setPartiallySelected(dataTree) {
    dataTree.forEach((value, index, arr) => {
      // console.log(arr, index);
      this.arrayPath.push(index);
        if(!value.checked) {
            if(value.children.length > 0) {
                const childrenChecked = value.children.some(childValues => {
                    if(childValues.checked) {
                        return true;
                    }
                }) 
                if(!childrenChecked) {
                  this.setPartiallySelected(value.children, value.parent)
                } else {
                    // update parent
                    this.setSelectedPro(this.arrayPath, 0, this.checkboxTree);
                    this.arrayPath.pop();
                }
            } else {
              this.arrayPath = [];
            }
        } else {

        }
        if(arr.length - 1 === index) {
          console.log(arr.length - 1, index)
          this.arrayPath.pop();
        }

    })
  }

  setSelectedPro(parentPath, currentIndex, dataTree) {
    console.log("--------------");
    console.log(parentPath);
    // console.log(parentPath, currentIndex, parentPath[currentIndex]);
    console.log(dataTree[parentPath[currentIndex]]); 
    currentIndex++;
    if(currentIndex < parentPath.length ) {
      dataTree[parentPath[currentIndex - 1]].isPartiallyChecked = true;
      this.setSelectedPro(parentPath, currentIndex, dataTree[parentPath[currentIndex - 1]].children);
    }       
  }
}

var obj = new checkbox();
obj.setPartiallySelected(tree);
var树=[{
价值:“A”,
勾选:假,
所选儿童:假,
儿童:[{
值:“AA”,
勾选:假,
所选儿童:假,
儿童:[],
家长:“A”
}, {
值:“AB”,
勾选:假,
所选儿童:假,
儿童:[{
值:“ABA”,
勾选:假,
所选儿童:假,
儿童:[{
值:“ABAA”,
勾选:假,
所选儿童:假,
儿童:[],
家长:“ABA”
}, {
值:“ABAB”,
勾选:假,
所选儿童:假,
儿童:[],
家长:“ABA”
}, {
值:“ABAC”,
核对:对,
所选儿童:假,
儿童:[],
家长:“ABA”
}, {
值:“ABAD”,
勾选:假,
所选儿童:假,
儿童:[],
家长:“ABA”
}],
家长:“AB”
}],
家长:“A”
}, {
值:“AC”,
勾选:假,
所选儿童:假,
儿童:[{
价值:“ACA”,
勾选:假,
所选儿童:假,
儿童:[],
家长:“AC”
}],
家长:“A”
}, {
价值:“广告”,
勾选:假,
所选儿童:假,
儿童:[],
家长:“A”
}],
父项:null
}]
类复选框{
构造函数(){
this.checkboxTree=tree;
this.arrayPath=[];
}
setPartiallySelected(数据树){
dataTree.forEach((值、索引、arr)=>{
//控制台日志(arr,索引);
this.arrayPath.push(索引);
如果(!value.checked){
如果(value.children.length>0){
const childrenChecked=value.children.some(childValues=>{
if(childValues.checked){
返回true;
}
}) 
如果(!childrenChecked){
此.setPartiallySelected(value.children,value.parent)
}否则{
//更新父项
this.setSelectedPro(this.arrayPath,0,this.checkboxTree);
this.arrayPath.pop();
}
}否则{
this.arrayPath=[];
}
}否则{
}
if(arr.length-1==索引){
console.log(arr.length-1,索引)
this.arrayPath.pop();
}
})
}
setSelectedPro(父路径、当前索引、数据树){
console.log(“--------------”;
console.log(parentPath);
//log(parentPath、currentIndex、parentPath[currentIndex]);
log(dataTree[parentPath[currentIndex]];
currentIndex++;
if(currentIndex

您需要两个递归函数来计算和设置值。您还必须应用
obj.children.length
,以避免在
childrenChecked
数组为空时将self标记为
childrenChecked
-参考预期输出中的
ABAC
元素)

var树=[{
价值:“A”,
勾选:假,
所选儿童:假,
儿童:[{
值:“AA”,
勾选:假,
所选儿童:假,
儿童:[],
家长:“A”
}, {
值:“AB”,
勾选:假,
所选儿童:假,
儿童:[{
值:“ABA”,
勾选:假,
所选儿童:假,
儿童:[{
值:“ABAA”,
勾选:假,
所选儿童:假,
儿童:[],
家长:“ABA”
}, {
值:“ABAB”,
勾选:假,
所选儿童:假,
儿童:[],
家长:“ABA”
}, {
值:“ABAC”,
核对:对,
所选儿童:假,
儿童:[],
家长:“ABA”
}, {
值:“ABAD”,
勾选:假,
所选儿童:假,
儿童:[],
家长:“ABA”
}],
家长:“AB”
}],
家长:“A”
}, {
值:“AC”,
勾选:假,
所选儿童:假,
儿童:[{
价值:“ACA”,
勾选:假,
所选儿童:假,
儿童:[],
家长:“AC”
}],
家长:“A”
}, {
价值:“广告”,
勾选:假,
所选儿童:假,
儿童:[],
家长:“A”
}],
父项:null
}]
让isChecked=obj=>{
返回obj.checked | | obj.children.some(x=>isChecked(x));
};
让setChildSelected=obj=>{
让childSelected=obj.childrence.length>0&&isChecked(obj);
obj.children=obj.children.map(setChildSelected);
返回{…obj,childSelected};
};
log(tree.map(setChildSelected))使用递归:

 function setSelected(node) {
   node.children.forEach(setSelected);

   node.childSelected = node.children.some(child => child.selected || child.childSelected);
 }

谢谢你这么好的回答。然而,我不明白发生了什么。你能补充一些例子吗?那太好了!什么样的例子?我建议您使用调试器并逐步完成代码。。。