【问题标题】:Immutable.js structure (updating nested map)?Immutable.js 结构(更新嵌套地图)?
【发布时间】:2016-01-15 19:57:56
【问题描述】:

我有一个深度嵌套的不可变结构,其中包含地图和列表。我不确定在结构中更新嵌套映射的最佳方法(id:356 的节点)。

我创建了一个搜索列表的函数,我找到了目标地图,我更新了它。但是结构完好无损!!知道我做错了什么吗?

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);

【问题讨论】:

    标签: immutable.js


    【解决方案1】:

    递归!

    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": []
                }
              ]
            }
          ]
        }
      ]
    }
    

    【讨论】:

    • 请注意,这个和原来的区别在于改变的值被传回堆栈。如果您使用的是不可变结构,则无法对其进行变异。如果您需要进行更改,您必须创建一个新的并传递它。原始对象通过调用set 创建新对象,但随后将其掉落在地板上。
    • 谢谢。但是这个解决方案总是返回一个新的不可变结构,即使没有值改变。 var updatedData = search(data, 356, (node) => node.set('c', false)); console.log(updatedData === 数据); // 即使什么都没有改变也总是假的
    • @AshrafFayad 当然是的。这就是不可变结构的意义所在。它们不会变异。如果您想要可变结构,请不要使用 ImmutableJS。
    • @AshrafFayad facebook.github.io/immutable-js/docs/#/Map/set 始终返回一个新副本,无论值是否已更改。如果您不希望这样,请检查该值,如果新值不同,则仅调用 set()
    猜你喜欢
    • 2020-06-09
    • 2017-02-19
    • 2017-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多