使用键简化对象的设置值

时间:2017-01-04 04:16:43

标签: javascript reactjs underscore.js

有没有办法简化以下代码?可能是通过使用下划线js,我浏览了文档,但找不到任何可以帮助我解决动态键值对的问题。

对象:

this.state = {
        media : {
            video : "",
            photos : [{
                title : "Storefront",
                url : "https://cdn.filepicker.io/api/file/cHyLd9KtSNibpsGlQsny",
                category : {
                    interior : false,
                    exterior : true,
                    closeup : false
                },
                display : {
                    preview : false,
                    featured : true,
                    none : false
                },
                size : "800 x 600",
                attribution_link : "",
                attribution_text : "",
                description : ""
            },
            {
                ...
            }]
       }
}

我正在使用react,而handleDisplayClick(e)方法正在调用,e将具有密钥名称,我需要将其更新为true,其余为false。



handleDisplayClick = (e) => {
        var stateCopy = Object.assign({}, this.state);
        if(e == "preview"){
            stateCopy.media.photos[this.state.media.selectedMediaIndex].display.preview = true;
            stateCopy.media.photos[this.state.media.selectedMediaIndex].display.featured = false;
            stateCopy.media.photos[this.state.media.selectedMediaIndex].display.none = false;
        }
        else if(e == "featured"){
            stateCopy.media.photos[this.state.media.selectedMediaIndex].display.preview = false;
            stateCopy.media.photos[this.state.media.selectedMediaIndex].display.featured = true;
            stateCopy.media.photos[this.state.media.selectedMediaIndex].display.none = false;
        }
        else{
            stateCopy.media.photos[this.state.media.selectedMediaIndex].display.preview = false;
            stateCopy.media.photos[this.state.media.selectedMediaIndex].display.featured = false;
            stateCopy.media.photos[this.state.media.selectedMediaIndex].display.none = true;
        }
        this.setState(stateCopy);
    }




3 个答案:

答案 0 :(得分:2)

识别模式并避免重复代码。例如。无需一遍又一遍地访问stateCopy.media.photos[this.state.media.selectedMediaIndex]。只需将值赋给变量并使用该变量即可。

这是一个较短的实现:

// assuming `e` is either "preview", "featured" or "none"
const photo = stateCopy.media.photos[this.state.media.selectedMediaIndex];
['preview', 'featured', 'none'].forEach(
  property => photo.display[property] = property === e
);

或没有循环:

// assuming `e` is either "preview", "featured" or "none"
Object.assign(
  stateCopy.media.photos[this.state.media.selectedMediaIndex],
  {
    preview: e === 'preview',
    featured: e === 'featured',
    none: e === 'none',
  }
);

另请注意,var stateCopy = Object.assign({}, this.state);只是副本。 stateCopy.media.photos[this.state.media.selectedMediaIndex]this.state.media.photos[this.state.media.selectedMediaIndex]指的是同一个对象,所以我认为你不会从中获得任何东西。如果要创建深层副本,则需要使用immutable-helper,如另一个答案所示。

答案 1 :(得分:1)

我使用immutability-helper包而不是underscore.js。我不知道使用它的优点或缺点,但它可以像这样工作

import update from 'immutability-helper';
......
this.state = {
        media : {
            video : "",
            photos : [{
                title : "Storefront",
                url : "https://cdn.filepicker.io/api/file/cHyLd9KtSNibpsGlQsny",
                category : {
                    interior : false,
                    exterior : true,
                    closeup : false
                },
                display : {
                    preview : false,
                    featured : true,
                    none : false
                },
                size : "800 x 600",
                attribution_link : "",
                attribution_text : "",
                description : ""
            },
            {
                ...
            }]
       }
}

update(this.state, {
    media: {
       photos: {
          0: {
              display: {
                  preview: {
                     $set: (e === 'preview') ? true : false
                  }
                  featured: {
                     $set: (e === 'featured') ? true : false
                  }
                  none: {
                     $set: (e === 'none') ? true : false
                  }
              }
          }

       }
    }
})

答案 2 :(得分:1)

这样的东西适用于动态属性(在外部或内部设置选项等)并覆盖如果你缺少对象上的一些键并且不想添加它们:

handleDisplayClick = (e) => {
    let stateCopy = Object.assign({}, this.state);
    let options = ['preview', 'featured'];
    e = (options.indexOf(e) > -1) ? e : 'none';
    Object.keys(stateCopy.media.photos[this.state.media.selectedMediaIndex].display).foreach(key => {
        stateCopy.media.photos[this.state.media.selectedMediaIndex].display[key] = (key === e);
    });
    this.setState(stateCopy);
}