如何将存储中的对象的动态属性用作 v 模型?



我一直在思考这个问题,但我不太想出这样做的方法。

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

举个例子:

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] 不要在突变处理程序之外更改 vuex 存储状态"。

我相信我明白为什么会发生这种情况:由于组件的计算属性指向对象(而不是要更改的属性),因此 v-model 将尝试更改深层属性,从而强制对存储进行更改,这将在组件甚至在对象上调用 set() 方法之前抛出错误, 右?

所以我想知道的是,

如何正确解决这个问题? 我的真实场景是,我正在构建一个带有复选框的动态过滤器,在运行时我不知道它会有多少选项。这意味着我将循环浏览我的选项来创建复选框,但随后数据绑定必须采用"values[]"的形式。这就是我头痛的开始。

提前谢谢大家

来自 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,您直接使用商店模型。

最新更新