2016-01-15 49 views
1

我有一个深深的嵌套不可变的结构与地图和列表。我不确定在结构中更新嵌套地图的最佳方式(具有ID:356的节点)。Immutable.js结构(更新嵌套地图)?

我创建了一个函数来搜索列表,我找到了目标地图,我更新它。但结构保持完好!任何想法我做错了什么?

https://jsbin.com/sadoni/1/edit?js,console

var structure = Immutable.fromJS(
     { 
      someKey:{id:1}, 
      links:[ 
       {id:123, c:false, chd:[]}, 
       {id:134, c:false, chd:[ 
        {id:212, c:false, chd:[ 
         {id:245, c:false, chd:[]}, 
         {id:256, c:false, chd:[]} 
        ]}, 
        {id:145, c:false, chd:[]}, 
        {id:156, c:false, chd:[]}, 
        {id:213, c:false, chd:[ 
         {id:313, c:false, chd:[]}, 
         {id:314, c:false, chd:[ 
          {id:345, c:false, chd:[]}, 
          {id:356, c:false, chd:[]} 
         ]} 
        ]} 
       ]} 

      ] 
     } 
    ); 


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _findNode 
    function _findNode(nodes, func, cb){ 
     let found = false; 
      var findInTree = (nodes, func) => { 
       if(nodes && nodes.size > 0){ 
        nodes.forEach(node => { 
         if(found === false){ 
          if (func(node) === true) { 
           found = true; 
           cb(node, nodes); 
          } else { 
           let chd = node.get('chd'); 
           if(chd && chd.size > 0 && found === false){ 
            findInTree(chd, func); 
           } 
          } 
         } 
        }); 
       } 
      }; 
      findInTree(nodes, func, cb); 
    } 


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _filter function 
function filter(link){ return link.get('id')===356; } 

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _find the links array inside the tree 
var links = structure.get('links'); 

function changeTheNode(node, nodes){ 
    console.log(nodes.get(1).toJS()); // log nodes array before the update 
    var index = nodes.findIndex(function(n){ return n === node; }); 
    nodes = nodes.update(index, function(itm){ return itm.set('c', true); }); 
    // nodes array changed 
    console.log(nodes.get(1).toJS()); 

    // structure tree is still the same :(
    //console.log(structure.toJS()); 
} 

_findNode(links, filter, changeTheNode); 

回答

0

递归!

var data = Immutable.fromJS({ 
    id:134, c:false, chd:[ 
     {id:212, c:false, chd:[ 
      {id:245, c:false, chd:[]}, 
      {id:256, c:false, chd:[]} 
     ]}, 
     {id:145, c:false, chd:[]}, 
     {id:156, c:false, chd:[]}, 
     {id:213, c:false, chd:[ 
      {id:313, c:false, chd:[]}, 
      {id:314, c:false, chd:[ 
       {id:345, c:false, chd:[]}, 
       {id:356, c:false, chd:[]} 
      ]} 
     ]} 
    ] 
}); 

function search(val, target, changeTheNode) { 
    if (val.get('id') === target) { 
     return changeTheNode(val); 
    } 

    return val.set('chd', 
     val.get('chd') 
     .map((v) => search(v, target, changeTheNode)) 
    ); 
} 

var updatedData = search(data, 356, (node) => node.set('c', true)) 

结果是

{ 
    "id": 134, 
    "c": false, 
    "chd": [ 
    { 
     "id": 212, 
     "c": false, 
     "chd": [ 
     { 
      "id": 245, 
      "c": false, 
      "chd": [] 
     }, 
     { 
      "id": 256, 
      "c": false, 
      "chd": [] 
     } 
     ] 
    }, 
    { 
     "id": 145, 
     "c": false, 
     "chd": [] 
    }, 
    { 
     "id": 156, 
     "c": false, 
     "chd": [] 
    }, 
    { 
     "id": 213, 
     "c": false, 
     "chd": [ 
     { 
      "id": 313, 
      "c": false, 
      "chd": [] 
     }, 
     { 
      "id": 314, 
      "c": false, 
      "chd": [ 
      { 
       "id": 345, 
       "c": false, 
       "chd": [] 
      }, 
      { 
       "id": 356, 
       "c": true, 
       "chd": [] 
      } 
      ] 
     } 
     ] 
    } 
    ] 
} 
+1

注意,这和原来的不同之处在于改变的值被传递回堆栈。如果你使用不可变的结构,你不能改变它。如果您需要进行更改,您必须创建一个新的并传递给您。原件通过调用'set'来创建新对象,但是然后将其放在地板上。 –

+0

谢谢。但是这个解决方案总是返回一个新的不可变结构,即使没有值被改变。 var updatedData = search(data,356,(node)=> node.set('c',false)); console.log(updatedData === data); //即使没有改变,也总是为假 –

+1

@AshrafFayad当然是。这是不可改变的结构。他们不会变异。如果你想要可变结构不使用ImmutableJS。 –