lau*_*kok 10 vue.js vuex nuxt.js
为什么我会收到此错误:
错误[vuex]不要在变异处理程序之外改变vuex存储状态.
这是什么意思?
当我尝试输入编辑输入文件时会发生这种情况.
页/待办事项/ index.vue
<template>
<ul>
<li v-for="todo in todos">
<input type="checkbox" :checked="todo.done" v-on:change="toggle(todo)">
<span :class="{ done: todo.done }">{{ todo.text }}</span>
<button class="destroy" v-on:click="remove(todo)">delete</button>
<input class="edit" type="text" v-model="todo.text" v-todo-focus="todo == editedTodo" @blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" @keyup.esc="cancelEdit(todo)">
</li>
<li><input placeholder="What needs to be done?" autofocus v-model="todo" v-on:keyup.enter="add"></li>
</ul>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
data () {
return {
todo: '',
editedTodo: null
}
},
head () {
return {
title: this.$route.params.slug || 'all',
titleTemplate: 'Nuxt TodoMVC : %s todos'
}
},
fetch ({ store }) {
store.commit('todos/add', 'Hello World')
},
computed: {
todos () {
// console.log(this)
return this.$store.state.todos.list
}
},
methods: {
add (e) {
var value = this.todo && this.todo.trim()
if (value) {
this.$store.commit('todos/add', value)
this.todo = ''
}
},
toggle (todo) {
this.$store.commit('todos/toggle', todo)
},
remove (todo) {
this.$store.commit('todos/remove', todo)
},
doneEdit (todo) {
this.editedTodo = null
todo.text = todo.text.trim()
if (!todo.text) {
this.$store.commit('todos/remove', todo)
}
},
cancelEdit (todo) {
this.editedTodo = null
todo.text = this.beforeEditCache
},
},
directives: {
'todo-focus' (el, binding) {
if (binding.value) {
el.focus()
}
}
},
}
</script>
<style>
.done {
text-decoration: line-through;
}
</style>
Run Code Online (Sandbox Code Playgroud)
商店/ todos.js
export const state = () => ({
list: []
})
export const mutations = {
add (state, text) {
state.list.push({
text: text,
done: false
})
},
remove (state, todo) {
state.list.splice(state.list.indexOf(todo), 1)
},
toggle (state, todo) {
todo.done = !todo.done
}
}
Run Code Online (Sandbox Code Playgroud)
我有什么想法可以解决这个问题?
Bad*_*bet 16
在属于Vuex的状态上使用v-model可能有点棘手.
你v-model在todo.text这里使用过:
<input class="edit" type="text" v-model="todo.text" v-todo-focus="todo == editedTodo" @blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" @keyup.esc="cancelEdit(todo)">
Run Code Online (Sandbox Code Playgroud)
用于:value读取值和/ v-on:input或v-on:change执行在显式Vuex变异处理程序内执行变异的方法
此问题在此处理:https://vuex.vuejs.org/en/forms.html
kis*_*ssu 14
此错误可能是由于您浅克隆了一个对象。
这意味着您尝试复制一个对象,但对象不是原始类型(如String或Number),因此它是通过引用而不是值传递的。
在这里,您认为您将一个对象克隆到了另一个对象中,而您仍在引用旧的对象。由于你正在改变旧的,所以你得到了这个很好的警告。
这是Vue3 文档中的 GIF (在我们的案例中仍然相关)。
在左侧,它显示了一个对象(杯子)没有被正确克隆>>通过引用传递。
在右侧,它已正确克隆 >> 按值传递。改变这个并不会改变原来的

管理此错误的正确方法是使用,这是在 Nuxt 中有效lodash加载它的方法:
lodash-es,例如:yarn add lodash-es,这是一个优化的tree-shakable lodash ES模块nuxt.config.js使用以下内容将其转译为您的build: {
transpile: ['lodash-es'],
}
Run Code Online (Sandbox Code Playgroud)
.vue像这样将其加载到您的组件中<script>
import { cloneDeep } from 'lodash-es'
...
const properlyClonedObject = cloneDeep(myDeeplyNestedObject)
...
</script>
Run Code Online (Sandbox Code Playgroud)
几个关键点:
JSON.parse(JSON.stringify(object))因为它确实可以处理一些边缘情况structuredClone如果您正在寻找深度复制的解决方案,那么它也是原生的并且性能相当好,完全绕过了 Lodash 的需要。小智 10
您好,我遇到了同样的问题,并使用以下方法之一克隆我的对象来解决它:
{ ...obj} //spread syntax
Object.assign({}, obj)
JSON.parse(JSON.stringify(obj))
Run Code Online (Sandbox Code Playgroud)
对于您的代码,我认为您需要替换这部分
computed: {
todos () {
// console.log(this)
return this.$store.state.todos.list
}
}
Run Code Online (Sandbox Code Playgroud)
有了这个
computed: {
todos () {
// console.log(this)
return {...this.$store.state.todos.list}
}
}
Run Code Online (Sandbox Code Playgroud)
我不确定这是否是最好的方法,但希望这对遇到相同问题的其他人有所帮助。
会用lodash就不头痛了
computed: {
...mapState({
todo: (state) => _.cloneDeep(state.todo)
})
}
Run Code Online (Sandbox Code Playgroud)
小智 5
以防万一有人仍然对此感到困扰,我通过复制/克隆商店状态来让我的代码正常工作。
对于你的情况,尝试这样的事情......
computed: {
todos () {
return [ ...this.$store.state.todos.list ]
}
}
Run Code Online (Sandbox Code Playgroud)
它基本上是一个扩展运算符,它会生成 todos.list 数组的克隆。这样,您就不会直接更改状态的值,只是不要忘记提交,以便您的突变将保存在商店中。
| 归档时间: |
|
| 查看次数: |
16129 次 |
| 最近记录: |