我有一个系统,它使用许多表单组件来根据输入的信息实时更新视图 . 当我第一次构建应用程序时,我主要使用v-model,本地组件数据和vue save状态来将数据保存在本地存储中,以便在重新加载页面时保持不变 .
然而,当我在程序扩展时转移到vuex时,这并不是那么简单,所以我决定使用带有getter和setter的计算属性的v-model,所以我不必为50多个不同的输入写入更改函数 . 我还意识到你可以为一个对象创建一个计算变量,并且仍然使用v-model来访问和更新该对象的属性,如下所示:
<div v-for="prof in info.profs">
<textarea v-model="prof.name" class="code-input uk-input" rows="1" cols="20"></textarea>
<textarea v-model="prof.email" class="code-input uk-input" rows="1" cols="25"></textarea>
<textarea v-model="prof.office" class="code-input uk-input" rows="1" cols="50"></textarea> <br>
</div>
info: {
get () {
return this.$store.getters.getInfo
},
set (payload) {
this.$store.commit('updateInfo', payload)
}
},
这很好用,商店更新每个属性的数据,而不必创建自己独立的计算变量,但由于某种原因,它不会在vue chrome dev工具上显示为已提交的变体“updateInfo”,当我使用时vuex的本地存储插件,如vuex-persistedstate或vuex-persist,它不会更改本地存储数据,直到我提交另一个正常结构的突变 . 现在我的解决方法是在组件中创建属性的本地副本,然后观察该属性的更改并提交到商店,这让我可以再次使用组件级别localstorage mixin,但我觉得必须有更好的执行此操作的方法不涉及为info中的每个属性编写更改函数或计算变量,因为在此应用程序中这将非常详细 .
data () {
return {
info: this.$store.getters.getInfo
}
},
watch: {
info: function(payload){
this.$store.commit('updateInfo', payload)
}
},
1 回答
实际上,两种方式都是错误的 . 将
strict: true
添加到您的商店,您会看到两种情况都会抛出错误 .在两种选择中,
prof
的name
,email
和office
属性都被直接修改(这违反了Vuex原则,规定每次变化都应该通过突变发生) .类似地,不是那个计算的setter(第一种情况),也不是那个观察者(第二种情况)被触发,因为你没有修改
item
,而是它的深层嵌套属性(例如name
) .最简单的解决方案,允许你仍然 use a mixin ,是抛弃
v-model
并使用:value
和@input
绑定 . 例:请注意,它使用
updateProf
方法,该方法提交变异(见下文)并进入mixin .这样所有修改都在突变中完成 . 最后要注意的是,如果你使用
:value
和@input
verbose,你可以创建一个custom directive来处理它 .JSFiddle link或下面的演示(相同代码) .
Keeping v-model
只是这样,没有人告诉我没有你能够继续使用
v-model
的方法 . 这个替代方案的关键点是深度克隆和深度克服的功能 . 我提供了两个简单/天真的实现,YMMV:JSFiddle link . 演示(与小提琴相同的代码)如下: