【问题标题】:How to use a dynamic property from an object from store as a v-model?如何使用来自 store 对象的动态属性作为 v-model?
【发布时间】:2019-05-29 01:00:39
【问题描述】:

我一直在思考这个问题,但我无法弄清楚如何做到这一点。

如何将输入数据绑定到存储对象属性? 含义:我的组件只知道store对象,但并不事先知道该对象包含哪些属性。

举个例子:

Vue.component('os-choice', {
  template: `
    <div>
      <h5>Select OS</h5>
  
      <div>
        <label class="checkbox">
          <input type="checkbox" value="linux" v-model="linux">
            Linux
        </label>
      </div>

      <div>
        <label class="checkbox">
          <input type="checkbox" value="macos" v-model="macos">
            MacOS
        </label>
      </div>

      <div>
        <label class="checkbox">
          <input type="checkbox" value="windows" v-model="windows">
            Windows
        </label>
      </div>

    </div>
  `,
  computed: {
    linux: {
      get() {
        return store.state.linux;
      },
      set(val) {
        store.commit('updateLinux', {
          linux: val
        });
      }
    },
    macos: {
      get() {
        return store.state.macos;
      },
      set(val) {
        store.commit('updateMacos', {
          macos: val
        });
      }
    },
    windows: {
      get() {
        return store.state.windows;
      },
      set(val) {
        store.commit('updateWindows', {
          windows: val
        });
      }
    },
  }  
});


Vue.component('os-choice2', {
  template: `
    <div>
      <h5>Select OS</h5>
  
        <div v-for="(value,index) in os" :key="index">
          <label class="checkbox">
            <input type="checkbox" value="index" v-model="value">
              {{index}}
          </label>
        </div>

      </div>

    </div>
  `,
  computed: {
    os: {
      get(){ return store.state.os; },
      set(event){
        var name = event.target.value;
        var value = event.target.checked;
        store.commit('updateOs', {name: name, value: value});
      }
    },
  }  
});


 const store = new Vuex.Store({
  state: {
    // initial state
    linux: true,
    macos: true,
    windows: false,
    os: {
      linux: true,
      macos: true,
      windows: false,
    }
  },
  mutations: {
    updateLinux(state, payload) {
      console.log('STORE: updated linux');
      state.linux = payload.linux;
    },
    updateMacos(state, payload) {
      console.log('STORE: updated MacOS');
      state.macos = payload.macos;
    },
    updateWindows(state, payload) {
      console.log('STORE: updated Windows');
      state.windows = payload.windows;
    },
    updateOs(state, payload) {
      console.log('STORE: updated OS');
      state.os[payload.name] = payload.value;
    }
  }
});



var app = new Vue({
  el: "#app",


  
})
.row{
  width: 100%;
}
.column{
  width: 50%;
}
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://unpkg.com/vuex@3.1.1/dist/vuex.js"></script>

<div id="app" style="text-align:center;">
  <div class="row">
    <div class="column">
      <os-choice></os-choice>
    </div>
    <div class="column">
      <os-choice2></os-choice2>
    <div>
  </div>
</div>

第一个组件效果很好。 第二个组件不更新存储:它生成错误“[vuex] Do not mutate vuex store state outside mutation handlers.”

我相信我明白为什么会发生这种情况:由于组件的计算属性指向对象(而不是被更改的属性),v-model 将尝试更改 deep 属性,从而强制更改 store这会在组件调用对象的 set() 方法之前引发错误,对吧?

那么我想知道的是如何正确处理这个问题?

我的真实场景是我正在构建一个带有复选框的动态过滤器,并且在运行时我不知道它会有多少选项。这意味着我将遍历我的选项来创建复选框,但是数据绑定必须采用“值 []”的形式。这就是我头疼的地方。

提前谢谢大家

【问题讨论】:

    标签: javascript vue.js vuex


    【解决方案1】:

    来自 VueJs 文档:

    自定义事件也可用于创建自定义输入 v 模型。请记住:

     <input v-model="searchText">
    

    做同样的事情:

     <input   v-bind:value="searchText"   v-on:input="searchText =
     $event.target.value"
     >
    

    在组件上使用时,v-model 会这样做:

     <custom-input   v-bind:value="searchText"   v-on:input="searchText =
     $event"
     ></custom-input>
    

    因此,您可以使用value 作为v-bind:value="value" 并映射事件以适当地更新商店,而不是使用v-model,例如:v-on:input="store.commit('store.commit('updateOs', event.target.value)"

    另一个组件可以正常工作,因为您完全按照 Vuex 推荐的方式进行操作:https://vuex.vuejs.org/guide/forms.html

    但是在v-for上,你是直接使用store模型的。

    【讨论】:

    • 有很多方法可以解决这个问题。另一个我能想到的解决方案是在组件上维护bind模型,而不是直接绑定到store,使用watch与store同步。
    • 感谢您的回答@Reuel。它回答了我的问题。我以前做过类似的事情,但是我遇到了初始值的问题,因为它们没有在运行时加载,我必须等待值准备好。但我一定是做错了什么,因为我刚刚在我的 codepen 上尝试了你的建议并且它有效。如果您愿意检查一下:codepen.io/oscarcarvalho/pen/GaXgPg 现在可以满足我的需要。谢谢
    猜你喜欢
    • 2020-01-05
    • 2020-01-06
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    • 2021-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多