有没有办法简化以下代码?可能是通过使用下划线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);
}

答案 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);
}