У меня есть следующий интерфейс:
Я постараюсь объяснить, что здесь происходит. У меня есть кнопка «Добавить сообщение». Когда я нажимаю на кнопку, у меня появляется новая форма с сообщением: заголовок, тело, изображение, язык (несколько вариантов выбора через этот плагин ). Я дважды нажал - у меня 2 сообщения. Просто.
Я не использую vue роутер. Реализация моей маршрутизации осуществляется с помощью бэкэнда. Это означает, что для каждого маршрута у меня новое состояние vuex.
Я собираюсь держать свои сообщения в vuex, но невозможно использовать v-model
для этого случая. Итак, я покажу свой код.
store:
export const store = new Vuex.Store({
state: {
messages: [],
// more props are here ...
},
mutations: {
setMessages(state, messages) {
state.messages = messages;
},
// more setters are here
},
getters: {
getMessages: state => {
return state.messages;
},
// more getters are here
},
actions: {
updateMessagesAction: function({commit}, value) {
console.log(value)
},
}
});
Компонент сообщений:
<template>
<div>
<button class="btn btn-outline-info" @click.prevent="createNewMessage">
<i class="fa fa-language"/> Add message
</button>
<div>
// now it works with local state, but I need to work with vuex
<div v-for="(message, index) in messages">
<button class="btn btm-sm btn-danger" @click="deleteMessage(index, message)"><i class="fa fa-remove"/>
</button>
<b-collapse collapsed :id="`collapse-${index}`">
<form>
<div class="form-group">
<label class="typo__label">Languages</label>
<multiselect
v-model="message.languages"
:options="getLanguagesOptions"
:multiple="true"
:close-on-select="true"
:clear-on-select="false"
:preserve-search="true"
placeholder="Languages"
label="name"
track-by="id"
>
</multiselect>
</div>
<div class="form-group">
<label for="title" class="typo__label">Title</label>
<input type="text" id="title" class="form-control" autocomplete="off" ??? how to bind it to vuex ???? I dont understand :(((>
</div>
<div class="form-group">
<label for="text" class="typo__label">Body</label>
<textarea class="form-control" id="text" ??? how to bind it to vuex ???? I dont understand :(((/>
</div>
<div class="form-group">
<div id="upload-image">
<div v-if="!message.imageSrc">
<h2>Image</h2>
<input type="file" ref="file" @change="onFileChange($event, message)">
</div>
<div v-else>
<img :src="message.imageSrc"/>
<button @click.prevent="removeImage($event, message)">Remove</button>
</div>
</div>
</div>
<hr class="mb-2">
</form>
</b-collapse>
</div>
</div>
</div>
</template>
<script>
// imports
export default {
async created() {
// set languages from servert to vuex
let res = (await axios.post(this.urlForGettingLanguagesFromServerProp)).data;
this.$store.commit('setLanguagesOptions', res);
},
name: "MessagesComponent",
props: {
urlForGettingLanguagesFromServerProp: String,
uploadImageUrl: String,
deleteImageUrl: String,
selectedLanguagesIdsProp: {
type: Array,
default: () => []
},
},
methods: {
...mapMutations(['setLanguagesSelected']),
...mapActions(['updateMessagesAction']),
createNewMessage: function () {
let message = {
languages: [],
languagesIds: [],
title: "",
text: "",
imageSrc: "",
imageDbId: 0
};
this.messages.push(message);
},
deleteMessage: function (index, message) {
this.removeImage("", message);
this.messages.splice(index, 1);
},
onFileChange: async function (e, message) {
// this method add send image on server and save to state db image id ant path
},
removeImage: function (event, message) {
// remove image from server
}
},
computed: {
...mapGetters(['getLanguagesOptions', 'getMessages'])
},
watch: {
messages: {
deep: true,
immediate: true,
handler(val, oldVal) {
let message = JSON.parse(JSON.stringify(val));
this.$store.commit("setMessages", message);
}
}
},
data() {
return {
messages: [],
}
}
}
</script>
Я вызываю этот компонент в родительском компоненте. В родительском компоненте я запускаю vuex во время операции обновления.
Как видите, этот компонент работает с локальным состоянием и синхронизирует локальное состояние с vuex. Это нормально для операции создания. Я могу отправлять сообщения в vuex, затем я могу взять его в родительском компоненте с другой информацией и отправить на сервер. Но что делать с обновлением? У меня есть данные с сервера в родительском компоненте, но локальное состояние, конечно, пусто для компонента сообщений. Как привязать все сообщения к vuex и иметь возможность изменять каждое сообщение отдельно? Я имею в виду, например, изменить заголовок первого сообщения и сразу же добавить его в vuex? Пожалуйста, помогите мне улучшить этот компонент.