如何访问父节点和子节点

时间:2018-05-22 16:02:33

标签: javascript reactjs

我使用rc-tree,一个版本的tree.js做出反应,我不知道如何创建一个方法,当检查树项时,更改该元素,父项及其子项的属性。

例如:

  • 如果我点击New Folder1更改New Folder1项目上的选中值, 新的Folder2,新的Folder3,最后是layer12。

  • 如果我点击layer12更改了layer12,New Folder3上的选中值, 新文件夹2,最后是新文件夹。

  • 如果我点击Folder2上的新Folder2更改选中的值, Folder1,Folder3,最后是layer12。

这是一个json架构:

{
    "name": "New Folder1",
    "key": "0-625",
    "isLeaf": false,
    "type": "folder",
    "expanded": false,
    "checked": true,
    "children": [{
            "name": "New Folder2",
            "key": "0-629",
            "isLeaf": false,
            "type": "folder",
            "expanded": false,
            "checked": true,
            "children": [{
                "name": "New Folder3",
                "key": "0-623",
                "isLeaf": false,
                "type": "folder",
                "expanded": false,
                "checked": true,
                "children": [{
                    "name": "layer12",
                    "key": "0-99",
                    "isLeaf": true,
                    "type": "layer",
                    "checked": true
                }]
            }]
        }]
},

我发现这个方法在你检查时查找节点和树上的项目。但是如何更改子节点和父节点。

function getNodeByKey(key, node){
    var reduce = [].reduce;
    function runner(result, node){
        if(result || !node) return result;
        return node.key === key && node || //is this the proper node?
            runner(null, node.children) || //process this nodes children
            reduce.call(Object(node), runner, result);  //maybe this is some ArrayLike Structure
    }
    return runner(null, node);
}

编辑:

在React中,您需要使用ref属性才能访问节点元素,然后您可以使用javascript:reactjs

访问子节点和父节点

要访问儿童和家长,我想我必须使用childNodesparentNodenextSiblingpreviousSibling

但如何使用ref属性???因为它是一个节点数组

render() {
    const loop = (data) => {
        return data.map((item) => {
            if (item.children && item.children.length) {
                return <TreeNode ref={this.myRef} title={item.name} key={item.key} checked={item.checked} >{loop(item.children)}</TreeNode>;
            }
            return (
                <TreeNode ref={this.myRef} title={item.name} key={item.key} isLeaf={item.isLeaf} checked={item.checked}  />
            );
        });
    };
    return (
        <div className="draggable-container">
            <Tree
                // Expand
                expandedKeys={this.state.expandedKeys}
                onExpand={this.onExpand} autoExpandParent={this.state.autoExpandParent}
                // Draggable
                draggable
                onDragStart={this.onDragStart}
                onDragEnter={this.onDragEnter}
                onDrop={this.onDrop}
                // Select && Check
                onSelect={this.onSelect}
                checkable onCheck={this.onCheck} checkedKeys={this.state.checkedKeys} >
                { loop(this.state.treeData) }
            </Tree>
        </div>  
    );
}

onCheck = (checkedKeys, event) => {
   how can get node checked??? it always returns last node
   const node = this.myRef.current;
   console.log(node)
}

2 个答案:

答案 0 :(得分:1)

所以...关于你的&#39; ref&#39;问题:您将它们全部分配给同一个变量,您应该为每个节点生成ref-variable:

 this.myRefs = {};

<TreeNode ref={itemRef=>this.myRefs[item.key]=itemRef} title={item.name} key={item.key} checked={item.checked} >{loop(item.children)}</TreeNode>

因此,您可以通过其密钥访问每个节点。

实现它的另一种方法是分配更有用的键:

{
    "name": "New Folder1",
    "key": "0",
    "isLeaf": false,
    "type": "folder",
    "expanded": false,
    "checked": true,
    "children": [{
            "name": "New Folder2",
            "key": "0.0",
            "isLeaf": false,
            "type": "folder",
            "expanded": false,
            "checked": this.state.keysCheckedStatus['0.0'],
            "children": [{
                "name": "New Folder3",
                "key": "0.0.0",
                "isLeaf": false,
                "type": "folder",
                "expanded": false,
                "checked": this.state.keysCheckedStatus['0.0.0'],
                "children": [{
                    "name": "layer12",
                    "key": "0.0.0.0",
                    "isLeaf": true,
                    "type": "layer",
                    "checked":  this.state.keysCheckedStatus['0.0.0.0']
                },{
                    "name": "layer13",
                    "key": "0.0.0.1",
                    "isLeaf": true,
                    "type": "layer",
                    "checked":  this.state.keysCheckedStatus['0.0.0.1']
                }]
            }]
        }]
}

onCheck = (checkedKeys, event) => {
  let keysCheckedStatus = this.state.keysCheckedStatus;
   for(let key in checkedKeys){
      let connectedKeys= Object.keys(this.state.keysCheckedStatus)
                         .filter(k=> (k.length > key.length) && k.startsWith(key)) || (key.startsWith(k));
      for(let connectedKey in connectedKeys){
         keysCheckedStatus[connectedKey]=true;
      }
   }
  this.setState({keysCheckedStatus});
}

答案 1 :(得分:0)

这是我的解决方案,因为我的想法是使用所有树信息节点修改treeData:

onCheck = (checkedKeys, event) => {
    // console.log(this.treeData);
    const checkedKey = event.node.props.eventKey;
    this.updateItemChecked(checkedKey);
    this.setState({ checkedKeys: checkedKeys }, () => {
        this.props.parentTree(this.treeData);
    });
}

updateItemChecked = (key) => {
    var result = getNodeByKey(key, this.treeData);
    if (result.type.localeCompare('folder') !== 0) {
        if (result.checked === true ) {
            result.checked = false;
        } else {
            result.checked = true;     
        }
    } else {
        this.checkIfFolderHasItem(result);
    }

}

checkIfFolderHasItem = (result) => {
    if ( result.children && result.children.length > 0) {
        result.children.forEach( (item) => {
            if (item.type.localeCompare('folder') !== 0) {
                this.updateItemChecked(item.key);
            } else {
                this.checkIfFolderHasItem(item);
            }
        });
    }
}

// Expand
onExpand = (expandedKeys, event) => {
    // console.log('onExpand', expandedKeys);
    const checkedKey = event.node.props.eventKey;
    this.updateFolderExpanded(checkedKey);
    this.setState({ expandedKeys, autoExpandParent: false }, ()=> {
        this.props.parentTree(this.treeData);
    });
}

updateFolderExpanded = (key) => {
    var result = getNodeByKey(key, this.treeData);
    if (result.type.localeCompare('folder') === 0) {
        if (result.expanded === true ) {
            result.expanded = false;
        } else {
            result.expanded = true;     
        }
    }
}

render() {
    const loop = (data) => {
        return data.map((item) => {
            if (item.children && item.children.length) {
                return <TreeNode title={item.name} key={item.key} checked={item.checked} >{loop(item.children)}</TreeNode>;
            }
            return (
                <TreeNode title={item.name} key={item.key} isLeaf={item.isLeaf} checked={item.checked}  />
            );
        });
    };
    return (
        <div className="draggable-container">
            { 
                // (this.state.showModal) ? <TreeModal show={this.state.showModal} info={this.state.selected} treeData={this.state.treeData} parentTreeModal={this.doParentTreeModal} /> : null 
            }
            <Tree
                // Expand
                expandedKeys={this.state.expandedKeys}
                onExpand={this.onExpand} autoExpandParent={this.state.autoExpandParent}
                // Draggable
                draggable
                onDragStart={this.onDragStart}
                onDragEnter={this.onDragEnter}
                onDrop={this.onDrop}
                // Select && Check
                onSelect={this.onSelect}
                checkable onCheck={this.onCheck} checkedKeys={this.state.checkedKeys} >
                { loop(this.state.treeData) }
            </Tree>
        </div>  
    );
}

JSON示例:

[
    {
        "name": "Capas1",
        "key": "0-23",
        "isLeaf": false,
        "type": "folder",
        "expanded": true,
        "children": [{
                "name": "sectores",
                "key": "0-20",
                "isLeaf": true,
                "type": "layer",
                "checked": true
            },
            {
                "name": "distribucion",
                "key": "0-22",
                "isLeaf": true,
                "type": "layer",
                "checked": false
            }]
    }, 
    {
        "name": "Nueva Carpeta0",
        "key": "0-624",
        "isLeaf": false,
        "type": "folder",
        "expanded": false,
        "checked": false
    },
    {
        "name": "Nueva Carpeta1",
        "key": "0-625",
        "isLeaf": false,
        "type": "folder",
        "expanded": true,
        "children": [{
                "name": "Nueva Carpeta2",
                "key": "0-629",
                "isLeaf": false,
                "type": "folder",
                "expanded": true,
                "children": [{
                    "name": "Nueva Carpeta3",
                    "key": "0-623",
                    "isLeaf": false,
                    "type": "folder",
                    "expanded": true,
                    "children": [{
                        "name": "distribucion33",
                        "key": "0-99",
                        "isLeaf": true,
                        "type": "layer",
                        "checked": true
                    }]
                }]
            }]
    },
    {
        "name": "sectores1",
        "key": "0-27",
        "isLeaf": true,
        "type": "layer",
        "checked": true
    },
    {
        "name": "sectores12",
        "key": "0-89",
        "isLeaf": true,
        "type": "layer",
        "checked": false
    },
    {
        "name": "Capas 2",
        "key": "0-588",
        "isLeaf": false,
        "type": "folder",
        "expanded": false,
        "children": [{
            "name": "Capas 3",
            "key": "0-589",
            "isLeaf": false,
            "type": "folder",
            "expanded": false,
            "children": [{
                "name": "Prueba",
                "key": "0-36",
                "isLeaf": true,
                "type": "layer",
                "checked": false
                }]
            }]
    }
]