Как правильно изменять vuex state?
Имеем store.js:
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
"testObj": {
item1: "item_1"
}
},
mutations: {
SET_KEY(state) {
state.testObj.item3 = "item_3"
}
},
actions: {},
modules: {}
});
И два компонента:
- TestComponent:
<template>
<div>{{testObj}}</div>
</template>
<script>
import { mapState } from "vuex"
export default {
name: "TestComponent",
computed: {
...mapState({
testObj: (state) => state.testObj
})
}
}
</script>
- TestButton
<template>
<input type="button" value="Click" @click="onClick">
</template>
<script>
import { mapState } from "vuex"
export default {
name: "TestButton",
computed: {
...mapState({
testObj: (state) => state.testObj
})
},
methods: {
onClick: function() {
this.$set(this.testObj, "item2", "item_2")
this.$store.commit("SET_KEY")
}
}
}
</script>
При клике на кнопку я хочу реактивно изменять объект.
Я могу сделать это при помощи мутации this.$store.commit("SET_KEY") или же просто this.$set(this.testObj, "item2", "item_2").
Верно ли я понимаю, что оба варианта допустимы? Есть ли между ними какая-то разница, кроме очевидной возможности "переиспользовать" мутацию.
Ответы (2 шт):
const store = new Vuex.Store({
state: {
todos: [
{ text: "Learn JavaScript", done: true },
{ text: "Learn Vue", done: false },
{ text: "Play around in JSFiddle", done: false },
{ text: "Build something awesome", done: false },
{ text: "Learn Vuex", done: false }
]
},
actions: {
toggleTodo({ commit }, index) {
commit('toggleTodo', index);
}
},
mutations: {
toggleTodo(state, index) {
state.todos[index].done = !state.todos[index].done;
}
},
getters: {
todos: ({ todos }) => todos
}
});
new Vue({
el: "#app",
store,
computed: {
todos() {
return this.$store.getters.todos;
}
},
methods: {
toggle(index) {
this.$store.dispatch('toggleTodo', index);
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.5.1/vuex.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Todos с использованием Vuex:</h2>
<ol>
<li v-for="(todo, index) in todos">
<label>
<input type="checkbox" v-on:change="toggle(index)" v-bind:checked="todo.done">
<del v-if="todo.done">
{{ todo.text }}
</del>
<span v-else>
{{ todo.text }}
</span>
</label>
</li>
</ol>
</div>
Vue.set- Добавление свойства к реактивному объекту, гарантируя, что новое свойство также будет реактивным и будет вызвано обновление представления. Это пригодится для добавления новых свойств к реактивным объектам, поскольку иначеVueне может отследить эти изменения.
Единственным способом изменения состояния хранилища во Vuex являются мутации. Мутации во Vuex очень похожи на события: каждая мутация имеет строковый тип и функцию-обработчик. В этом обработчике и происходят, собственно, изменения состояния, переданного в функцию первым аргументом:
Вы должны понять, что первое всего-лишь обеспечивает создание реактивности свойств, а второе синхронное изменение состояния Vuex.
Мутации следуют правилам реактивности Vue
Это значит, что в мутациях вы можете использовать vue.set($vm.set) для добавления новых свойств, которые сразу же будут сделаны vue реактивными.
Не смотря на соблазн изменения данных из хранилища напрямую (в том числе и с помощью vue.set), не делайте этого, создатели vuex рекомендуют изменять состояние хранилища vuex только через мутации, потому ,что:
привнесение асинхронности в мутации могло бы изрядно затруднить понимание логики программы. Например, если вызываются два метода, оба с асинхронными коллбэками, изменяющими состояние приложения — как предсказать, какой из коллбэков будет вызван первым? Именно поэтому концепции изменений и асинхронности рассматриваются по отдельности. Во Vuex мутации — это синхронные транзакции:
- простым языком, чтобы избежать ошибок при расширении вашего приложения, для изменения данных хранилища vuex - используйте только мутации, потому, что они дают гарантию, что ваши данные будут изменены именно в той последовательности в которой вы будете инициировать их изменение
