Удаление данных Vuex
Я недавно начала изучать Vuex и сейчас делаю небольшое приложение календарь. Хочу удалить данные и чтобы это все было реактивно.
Мой компонент
...mapMutations(['deletePost']),
deleteTask(todo) {
this.$store.commit('deletePost', todo);
}
сама мутация
deletePost(state,post){
fetch(postsUrl + post.id, {
headers: {
'content-type': 'application/json',
},
method: 'POST',
body: JSON.stringify(post),
})
.then(() => state.post.splice(state.post.findIndex(p => p.id === post.id), 1))
}
state:{
posts:[]
},
Подскажите как это сделать(
Ответы (2 шт):
Дело в том что vue Observer не подписывается на значения массива. Он может быть подписан только на изменение ключей в data. После запроса тебе надо пнуть весь массив целиком, тогда Vue поймёт что пора прорисоваться.
Как пнуть Observer по зад, описано вот в этом ответе. https://stackoverflow.com/questions/48984877/vuejs-manually-trigger-an-update-into-observed-object-array
Cостояние хранилища Vuex — это реактивная переменная Vue, при возникновении мутации, зависящие от этого состояния компоненты Vue обновляются автоматически. Кроме того, это значит, что мутации Vuex имеют те же самые подводные камни, что и реактивность в обычном Vue.
Учитывая это, получается, что vuex по умолчанию, все что объявлено в state делает реактивным (это не значит, что нельзя добавить реактивные данные после инициализации), следуя правилам замены в массиве, вам достаточно, используя один из изменяемых или неизменяемых методов для массива, внести изменения в данные из state, чтобы компоненты, которые используют эти данные получили актуальное состояние vuex.
Приведу небольшой пример для наглядности (обратите внимание, что данные из state в компоненте используются через getters, получаются данные с сервера через actions, это дает возможность использовать асинхронность, в мутациях использовать таковую нет возможности, потому что мутации должны быть синхронными, чтобы быстро вносить изменения в state, после получения ответа от сервера - производятся мутации, чтобы синхронизировать состояние с сервера с состоянием vuex. Пример не является лучшей практикой, но хорошо демонстрирует некоторые возможности vuex:
const {
mapGetters,
mapMutations,
mapActions,
} = Vuex;
const store = new Vuex.Store({
state: {
posts_data: [],
},
getters: {
posts: (state) => state.posts_data
},
mutations: {
changePosts(state, posts) {
state.posts_data = posts
},
deletePost(state, id) {
state.posts_data = state.posts_data.filter((post) => post.id !== id)
},
},
actions: {
async findPosts({
commit
}, data) {
const posts = await fetch('http://jsonplaceholder.typicode.com/posts?_limit=5')
.then(response => response.json())
.then(json => commit('changePosts', json))
.catch(e => console.error(e))
return posts
},
async deletePostDb({
commit
}, post_id) {
const post = await fetch(`http://jsonplaceholder.typicode.com/posts/${post_id}`, {
method: 'DELETE',
})
.then(response => response.json())
.then((json) => {
commit('deletePost', post_id)
})
.catch(e => console.error(e))
return post
}
}
})
new Vue({
el: '#app',
store,
data: () => ({}),
computed: {
...mapGetters(['posts'])
},
methods: {
...mapActions(['findPosts', 'deletePostDb']),
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vuex"></script>
<div id="app">
<div>
<ul>
<li v-for="post in posts" :key="post.id">
{{post.id}} - {{ post.title }}
<button type="button" @click="deletePostDb(post.id)">Удалить</button>
</li>
</ul>
<button type="button" @click="findPosts">Найти посты</button>
</div>
</div>