我正试图通过Drag& Drop重新排列div与React / Redux,并且有一个奇怪的行为,我无法解释。我有以下减速机(可读性简化版)
代码中间有5个“console.log”。当我记录状态或结构时,Chrome控制台将打印已经重新排列的版本。为什么呢?
export default function reducer(
state={
structures: [],
elementUniqueCounter: 0,
hoveredElement: null,
DnD: {
dragContent: null,
dragOverContent: null,
dragContentTop: true,
dragStructure: null,
dragOverStructure: null,
dragStructureTop: true,
content: null,
mousepositon: {}
}
}, action) {
let DnD = Object.assign({}, state.DnD);
let structs = state.structures.slice();
switch (action.type) {
case "STOP_DRAG_CONTENT":
let cindex_source;
let index_source;
let cindex_target;
let index_target;
let foundTarget = false;
let foundSource = false;
structs.map(function (struct, index) {
struct.content.map(function (content, cindex) {
if(content.id === DnD.dragOverContent.props.id) {
cindex_target = cindex;
index_target = index;
foundTarget = true;
}
if(content.id === DnD.dragContent.props.id) {
cindex_source = cindex;
index_source = index;
foundSource = true;
}
});
});
console.log(state);
console.log(index_source);
console.log(cindex_source);
console.log(index_target);
console.log(cindex_target);
if(index_source !== undefined && cindex_source !== undefined && index_target !== undefined && cindex_target !== undefined) {
let copy = structs[index_source].content.slice(cindex_source, cindex_source+1)[0];
copy.content = DnD.content;
structs[index_source].content.splice(cindex_source, 1);
if (DnD.dragContentTop) {
structs[index_target].content.splice(cindex_target+1, 0, copy);
} else {
structs[index_target].content.splice(cindex_target, 0, copy);
}
}
DnD = {
dragContent: null,
dragOverContent: null,
dragContentTop: true,
dragStructure: null,
dragOverStructure: null,
dragStructureTop: true,
content: null,
mousepositon: {}
};
return {...state, DnD: DnD, structures: structs};
}
return state
}
答案 0 :(得分:1)
并不意味着它会在重新排列的版本发生之前打印出来。它正在打印一个你正在改变的对象。当你在控制台中查看对象时,突变已经发生。
使用splice
正在改变。
structs[index_source].content.splice(cindex_source, 1);
if (DnD.dragContentTop) {
structs[index_target].content.splice(cindex_target+1, 0, copy);
} else {
structs[index_target].content.splice(cindex_target, 0, copy);
}
编辑:
上述突变实际上是在改变state.structures
的嵌套属性。发生这种情况是因为.slice()返回原始对象的浅表副本。
slice()方法将数组的一部分的浅表副本返回到从头到尾选择的新数组对象(不包括结尾)。原始数组不会被修改。
浅拷贝中的对象只是指向state.structures
中对象的指针。因此,当您使用.splice()
时,您会改变这些引用的值。
这是一个片段来说明这一点。运行它来查看console.log
。
const people = [
{
name: "Joe",
age: "52"
},
{
name: "Sally",
age: "48"
}
];
const clonedPeople = people.slice();
console.log("people === clonedPeople: ", people === clonedPeople);
console.log("people[0] === clonedPeople[0]: ", people[0] === clonedPeople[0]);
const deeplyClonedPeople = JSON.parse(JSON.stringify(people));
console.log("people[0] === deeplyClonedPeople[0]: ", people[0] === deeplyClonedPeople[0]);

希望这有帮助!