如何深入克隆状态并在Vuex中回滚?

时间:2018-10-15 11:34:38

标签: javascript vue.js clone vuex deep-copy

在Vuex中,我想对树中的对象属性进行快照/克隆,对其进行修改,然后以后可以回滚到以前的快照。

背景
在应用程序中,用户可以在应用某些更改之前对其进行尝试。应用更改时,它们应影响主vuex树。用户还可以单击“取消”以放弃更改并返回到以前的状态。

示例:

state: {
  tryout: {},
  animals: [
    dogs: [
      { breed: 'poodle' },
      { breed: 'dachshund' },
    ]
  ]
}

用户进入“试用”模式,并将一个品种从poodle更改为chihuahua。然后,她决定放弃更改或应用更改。

state: {
  animals: [
    dogs: [
      { breed: 'poodle' },
      { breed: 'dachshund' },
    ]
  ],
  tryout: {
    animals: [
      dogs: [
        { breed: 'chihuahua' },
        { breed: 'dachshund' },
      ]
    ]
  }
}

丢弃(回滚到以前的状态):

state: {
  animals: [
    dogs: [
      { breed: 'poodle' },
      { breed: 'dachshund' },
    ]
  ],
  tryout: {}
}

应用(保存主vuex树中的更改):

state: {
  animals: [
    dogs: [
      { breed: 'chihuahua' },
      { breed: 'dachshund' },
    ]
  ],
  tryout: {}
}

什么是深度克隆状态,在克隆上进行更改,然后又放弃更改或应用更改的好的解决方案? 这里的示例非常基础,该解决方案必须适用于更复杂的对象/树。

编辑1:
有一个名为vuex-undo-redo的库,它基本上记录了突变,但是存在一些问题。在另一个堆栈溢出主题Going back to States like Undo Redo on Vue.js vuex中,建议使用vuex函数replaceState(state)

1 个答案:

答案 0 :(得分:2)

您可以将JSON.stringifyJSON.parsereplaceState一起使用。

在vuex中:

const undoStates = [];

// save state
undoStates.push(JSON.stringify(state));

// call state (remove from stack)
if (undoStates.length > 0) {
  this.replaceState(JSON.parse(undoStates.pop()));
}

这将创建整个状态的副本,但是您也可以使用商店的一部分:

const animalStates = [];

// save state
animalStates.push(JSON.stringify(state.animals));

// call state (remove from stack)
if (animalStates.length > 0) {
  let animals = JSON.parse(animalStates.pop());
  this.replaceState({...state, animals} );
}

这会将当前状态与您选择的对象(在本例中为动物)合并。