在 Vuex 中为同一组件实现双向数据绑定的不同方法

Posted

技术标签:

【中文标题】在 Vuex 中为同一组件实现双向数据绑定的不同方法【英文标题】:Different ways to implement two-way data binding for same component in Vuex 【发布时间】:2021-02-07 17:30:14 【问题描述】:

我有一个 地址 组件,它具有基本的地址形式,其中包含 名称、街道、城市、州、国家/地区等详细信息。 我将它用于来源目的地

示例模板

<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.(name, street, city, state, country) 在 state 和 Address 组件的 dest 应该改变 Address.dest.(name, street, city, state, country) 在州

我按照这个post 尝试使用props 和emit,vuex-map-fields,但没有成功。

我不知道实现它的正确方法是什么。

我将这个问题发布为菜鸟以获得帮助 正确的做法是什么?

【问题讨论】:

【参考方案1】:

如果我正确理解了您的问题,我会遵循以下模式:

Make API Call --> data is updated in Vuex --> picked up by computed prop in component

基本上,在我的组件中,我可以创建一个从 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>

现在,只要在 Vuex 中更新 Address 对象(通过 API 调用),这些计算出来的 props 将分别选择更改并更新 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);
  



【讨论】:

这解决了从 vuex 到 Address 组件的数据,如何将 Address 组件中的更改更新为 vuex 状态?我想实现双向数据绑定@nishkaush 首先定义一个mutation,它在接收到数据时会更新状态。然后从你的Vuex Action 中调用这个突变(在 API 调用成功并且实际上包含一些要更新的数据之后)。 @AkashPreet,如果您对解决方案感到满意,您能否将其标记为未来读者的答案。谢谢【参考方案2】:

您可以使用vuex getters 获取您的商店数据。 Vue 使用 vuex 辅助函数处理更优雅的将数据(two way binding)拉入组件的方式。你可以阅读更多关于 vuex 辅助函数here

// 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:  ) 

【讨论】:

感谢@Naren 的回答,但它仍然无法解决问题。如果我们更改地址组件的输入字段中的值,我想改变状态。例如:如果 API 返回 Address.src.name 作为 Naren(将存储在状态中),则页面将在 Address 的名称输入字段中加载 Naren。如果我将 Naren 更改为 Akash,那么它的状态应该会发生变异(Address.src.name 现在应该是 Akash)。 你不应该直接改变状态,你应该只使用突变。根据 Vuex 文档:The only way to actually change state in a Vuex store is by committing a mutation,阅读this 了解更多信息 如果您想从输入字段更改状态,请在存储中添加突变并使用该突变更新状态。 const mutations = changeName(state, name) state.Address.name = name

以上是关于在 Vuex 中为同一组件实现双向数据绑定的不同方法的主要内容,如果未能解决你的问题,请参考以下文章

Vuex(实现加减操作,Vue.set解决自定义属性没有双向数据绑定)

vue2.x双向数据绑定原理

vue2 props双向数据绑定问题

Angular 手动实现ngModal数据双向绑定

来实现一个缩水版Vuex

vue组件双向绑定key的作用