最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to deep clone the state and roll back in Vuex? - Stack Overflow

programmeradmin2浏览0评论

In Vuex I would like to take a snapshot / clone of an object property in the tree, modify it, and later possibly roll back to the former snapshot.

Background:
In an application the user can try out certain changes before applying them. When applying the changes, they should effect the main vuex tree. The user can also click «cancel» to discard the changes and go back to the former state.

Example:

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

User enters »Try out« mode and changes one breed from poodle to chihuahua. She then decides either to discard the changes or apply them.

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

Discard (rolls back to previous state):

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

Apply (saves the changes in main vuex tree):

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

What are good solutions to deep clone a state, make changes on the clone, and later on either discard the changes or apply them? The example here is very basic, the solution must work with more plex objects / trees.

Edit 1:
There is a library called vuex-undo-redo, which basically logs mutations, but has some problems. In another Stack Overflow topic Going back to States like Undo Redo on Vue.js vuex it is remended to use the vuex function replaceState(state).

In Vuex I would like to take a snapshot / clone of an object property in the tree, modify it, and later possibly roll back to the former snapshot.

Background:
In an application the user can try out certain changes before applying them. When applying the changes, they should effect the main vuex tree. The user can also click «cancel» to discard the changes and go back to the former state.

Example:

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

User enters »Try out« mode and changes one breed from poodle to chihuahua. She then decides either to discard the changes or apply them.

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

Discard (rolls back to previous state):

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

Apply (saves the changes in main vuex tree):

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

What are good solutions to deep clone a state, make changes on the clone, and later on either discard the changes or apply them? The example here is very basic, the solution must work with more plex objects / trees.

Edit 1:
There is a library called vuex-undo-redo, which basically logs mutations, but has some problems. In another Stack Overflow topic Going back to States like Undo Redo on Vue.js vuex it is remended to use the vuex function replaceState(state).

Share Improve this question edited Oct 15, 2018 at 13:39 Pwdr asked Oct 15, 2018 at 11:34 PwdrPwdr 3,7914 gold badges31 silver badges39 bronze badges 4
  • 1 The state is just an object right, you can deep clone it using any deep clone technique and then refer to the state object you want to use any given time. I don’t see why this is any different from other deep clone cases – Sven van de Scheur Commented Oct 15, 2018 at 11:38
  • 1 I assumed that it would produce unwanted side-effects when cloning / replacing the whole objects (reactivity). – Pwdr Commented Oct 15, 2018 at 11:42
  • 1 Hi! What if, you do a deep copy? Check this. – LakiGeri Commented Oct 15, 2018 at 14:22
  • 1 -1 for vuex-undo-redo, it has caused me a lot of headaches in the past few days. Starting from the fact that it attaches to every. single. ponent. of your app and tries to undo 37 times after only one mutation – Nikolay Dyankov Commented Apr 14, 2019 at 22:00
Add a ment  | 

1 Answer 1

Reset to default 5

You can use JSON.stringify and JSON.parse with replaceState.

In 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()));
}

That will create a copy of the entire state, but you can also use a part of the store:

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

This will merge the current state with an object you chose (like animals in this case).

发布评论

评论列表(0)

  1. 暂无评论