#vue.js #vuejs2 #vue-component #vuex #vuex-modules
#vue.js #vuejs2 #vue-компонент #vuex #vuex-модули
Вопрос:
У меня есть адресный компонент, который имеет базовую форму адреса с такими данными, как имя, улица, город, штат, страна. Я использую его для источника и назначения.
Образец шаблона
<div class="row">
<div class="col-6" id="src">
<Address :address="src" />
</div>
<div class="col-6" id="dest">
<Address :address="dest" />
</div>
</div>
Я использую действие Vuex (с модулем) для получения данных из API (который может возвращать или не возвращать какие-либо адресные данные) и изменения состояния моего хранилища.
Пример состояния:
Address:{
src:{
name:'',
street:'',
city:'',
state:'',
country:'',
},
dest:{
name:'',
street:'',
city:'',
state:'',
country:'',
}
}
Я хочу добиться двусторонней привязки данных между моими компонентами состояния и адреса посредством мутации.
Компонент адреса для src должен изменять Address.src.(название, улица, город, штат, страна) в состоянии, а компонент адреса для dest должен изменять Address.dest.(название, улица, город, штат, страна) в состоянии
Я попытался использовать props и emit, vuex-map-fields, следуя этому сообщению, и это не сработало.
Я не знаю, как правильно это реализовать.
Я публикую этот вопрос как новичок, чтобы получить помощь в том, как правильно это сделать?
Ответ №1:
Если я правильно понял вашу проблему, я следую приведенному ниже шаблону:
Make API Call --> data is updated in Vuex --> picked up by computed prop in component
В принципе, в моем компоненте я могу создать вычисляемый prop, который извлекает данные из хранилища Vuex, примерно так:
computed:{
sourceAddress(){
return this.$store.state.Address.src;
},
destinationAddress(){
return this.$store.state.Address.dest;
}
}
Затем я могу связать эти вычисленные реквизиты с моим адресным компонентом следующим образом:
<div class="row">
<div class="col-6" id="src">
<Address :address="sourceAddress" />
</div>
<div class="col-6" id="dest">
<Address :address="destinationAddress" />
</div>
</div>
Теперь всякий раз, когда объект Address будет обновляться в Vuex (через вызов API), эти вычисляемые реквизиты будут выбирать изменение и обновлять компонент Address соответственно.
// sample pseudo code
mutations:{
updateAddress(state, {type,payload}){
if(type==="destination"){
// update destination address
}
else {
//update source address
}
}
},
actions:{
makeApiCall(context){
// lets say call succeeds and you have some data to update for destination address
context.commit('updateAddress',{type:"destination", payload:"data-you-want-to-update});
}
}
Комментарии:
1. Это решает проблему передачи данных из vuex в адресный компонент, как я могу обновить изменение адресного компонента в состояние vuex? Я хочу добиться двусторонней привязки данных @nishkaush
2. Сначала определите a
mutation
, который при получении данных обновит состояние. Затем вызовите эту мутацию из вашегоVuex Action
(после успешного вызова API и фактически содержит некоторые данные для обновления).3. @AkashPreet, если вы довольны решением, не могли бы вы отметить его как ответ для будущих читателей. Спасибо
Ответ №2:
Вы можете использовать vuex getters
для получения данных вашего хранилища. Vue обрабатывает более элегантный способ извлечения данных ( two way binding
) в компоненты с помощью функций помощников vuex. Вы можете прочитать больше о вспомогательных функциях vuex здесь
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = {
Address: {
src: {
name:'',
street:'',
city:'',
state:'',
country:'',
},
dest: {
name:'',
street:'',
city:'',
state:'',
country:'',
}
}
}
const getters = {
src: state => state.Address.src,
desc: state => state.Address.desc
}
const mutations = {
setSrc(state, srcObj) { // You can play around this to optimize if you can
state.Address.src = srcObj
},
setDesc(state, descObj) {
state.Address.desc = descObj
}
}
const actions = {
makeApiCall({ commit }, { type, params }) {
yourApiCall(params).then((res) => {
if (type === 'src') { // You can play around this to optimize if you can
commit('setSrc', res)
} else {
commit('setDesc', res)
}
})
}
}
export default new Vuex.Store({ state, getters, mutations, actions})
//main.js
// all other imports
import store from './store'
new Vue({
el: '#app',
store
})
In your component
<Address :address="src"/>
<Address :address="desc"/>
import { mapGetters, mapActions } from 'vuex'
computed: {
...mapGetters(['src', 'desc']) // these are updated automatically when store changes and available on this.src/this.desc
},
methods: {
...mapActions(['makeApiCall']) // you can directly call using this // this.makeApiCall({ type: 'src', params: {} })
}
Комментарии:
1. Спасибо за ответ @Naren, но это все равно не решит проблему. Я хочу изменить состояние, если мы изменим значение в полях ввода компонента адреса. Например: если API возвращает Address.src.name как Naren (который будет сохранен в состоянии), тогда страница загрузится с Naren в поле ввода имени адреса. Если я изменю Naren на Akash, то он должен измениться в состоянии (Address.src.name сейчас должен быть Акаш).
2. вы не должны изменять состояние напрямую, вы должны делать только с мутациями. Согласно документам Vuex:
The only way to actually change state in a Vuex store is by committing a mutation
, прочитайте это для получения дополнительной информации3. Если вы хотите изменить состояние из поля ввода, добавьте мутацию в хранилище и обновите состояние с помощью этой мутации.
const mutations = { changeName(state, name) { state.Address.name = name }}