Javascript 如何在Vuex中设置参数和参数
我正在使用Vue.js、Vuex和Firebase构建一个待办事项列表应用程序。应用程序似乎工作正常,商店文件成功地管理了从firestore到firestore的输入待办事项的检索和呈现。但是,我仍然对在Vuex中设置参数有疑问。see store.js中的REMOVE_TODO函数似乎需要两个参数,尽管id是函数实际代码中引用的唯一参数。换句话说,如果去掉初始参数,在本例中,state将返回一个错误,该错误为:Function CollectionReference.doc要求其第一个参数的类型为非空字符串,但它是:一个自定义对象。我的问题是:如果id参数是函数中实际使用的唯一参数,为什么这个REMOVE_TODO函数需要有两个参数才能正常工作?为什么需要另一个论点?下面是我的代码。谢谢 app.vueJavascript 如何在Vuex中设置参数和参数,javascript,firebase,vue.js,google-cloud-firestore,vuex,Javascript,Firebase,Vue.js,Google Cloud Firestore,Vuex,我正在使用Vue.js、Vuex和Firebase构建一个待办事项列表应用程序。应用程序似乎工作正常,商店文件成功地管理了从firestore到firestore的输入待办事项的检索和呈现。但是,我仍然对在Vuex中设置参数有疑问。see store.js中的REMOVE_TODO函数似乎需要两个参数,尽管id是函数实际代码中引用的唯一参数。换句话说,如果去掉初始参数,在本例中,state将返回一个错误,该错误为:Function CollectionReference.doc要求其第一个参数的
<template>
<div id="app" class="container">
<input class="form-control" :value="newTodo" @change="getTodo" placeholder="I need to...">
<button class="btn btn-primary" @click="addTodo">Add New Post</button>
<ul class="list-group">
<li class="list-group-item" v-for="todo in this.$store.getters.getTodos" :key="todo.id">
{{todo.title}}
<div class="btn-group">
<button type="button" @click="remove(todo.id)" class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-remove-circle"></span> Remove
</button>
</div>
</li>
</ul>
</div>
</template>
<script>
export default {
beforeCreate: function() {
this.$store.dispatch('setTodo')
},
methods: {
getTodo(event) {
this.$store.dispatch('getTodo', event.target.value)
},
addTodo() {
this.$store.dispatch('addTodo')
this.$store.dispatch('clearTodo')
},
remove(id){
this.$store.dispatch('removeTodo', id)
}
},
computed: {
newTodo() {
return this.$store.getters.newTodo
},
todos(){
return this.$store.getters.todos
}
}
}
</script>
<style>
body {
font-family: Helvetica, sans-serif;
}
li {
margin: 10px;
}
</style>
这与Vuex无关,只是JavaScript函数调用的工作方式。参数是按位置传递的,而不是按名称传递的 您需要REMOVE_-TODO:state,id=>{但是state和id的名称在函数内部才是真正重要的。在函数外部,从调用方的角度来看,这些名称并不重要。它可以很容易地被REMOVE_-TODO:a,b=>{ 当Vuex调用变异时,它将状态对象作为第一个参数传递,负载作为第二个参数传递。实际上,它调用: 1.2.2.2.1.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2 我重申,争论的名字实际上并不重要,只是他们的立场 这是Vuex内部的,不是您可以直接控制的。如果您自己调用该函数,您可以传递任何您想要传递的函数,但您不是,也不应该传递。相反,您调用commit是非常正确的。您将所需的负载传递给commit,Vuex将执行其余操作,调用相关的变异并将其传递给t他描述了状态和有效载荷 相反,将函数定义为REMOVE_TODO:id=>{不会更改调用方传递的参数。第一个参数仍然是state对象。您将其命名为id,但这没有任何区别,它仍然是state对象 一般来说,尝试删除第一个参数的问题是,所有其他参数都会有效地向下移动,因此所需参数名称的位置不再与所传递参数的位置匹配。从末尾删除一个参数没有问题,因为其他参数不会移动位置。如果您只需要状态,而不需要有效负载,然后您可以删除第二个参数。没问题。API设计人员总是尝试将可选参数放在末尾,以便可以删除它们而不会导致任何问题 对于变异,有效载荷很容易是不必要的,但状态总是需要的。变异的关键是改变状态。如果你不改变状态,那么你就不应该使用变异 正如您的代码中所指出的,操作是异步的,而突变需要同步。但这不是您所拥有的。目前,您在突变中有很多对Firebase的异步调用。所有这些都需要转移到操作中。请注意,承诺总是异步的,因此如果您发现自己在突变中调用,那么就在突变中调用你做错了。唯一应该在突变中的部分是当你修改状态时 您还需要避免在Vuex存储中使用此选项。您应该发现,您需要的所有内容都可以通过传递给函数的参数访问。目前,您的变体中有this.errors=error和类似的选项。我假设应该是state.errors=error 更新: 按照评论中的要求: 设置待办事项状态,待办事项{ state.todos=todos } setTodo{commit}{ db.collection'items'.orderBy'created_at'.onSnapshotsnapshot=>{ 常数todos=[] snapshot.forEachdoc=>{ todos.push{id:doc.id,title:doc.data.title} } 提交“设置待办事项”,待办事项 } }
请注意,这不会试图处理可能的竞争条件。Hi JS_是一个很好的例子,但变异的原因是修改状态,你必须给它更新状态。你可以在状态中设置消息属性,并执行状态。如果状态是确定的,消息=文档被删除。消息=错误文档未被删除。@Birante,感谢您的帮助e反馈,尽管我不确定这是否完全回答了这个问题。这是否意味着变异函数在默认情况下需要状态作为参数,即使函数的代码中没有使用状态?是的,我认为这是一种最佳实践。谢谢你的反馈。你能提供一个stor的示例吗把承诺改写成行动?我想重新确认
我通过我的商店来反映你所写的内容。然后,我发现你在网站上写的不正确。如果您可以提供一段代码来展示一个示例,那将非常有用。谢谢@JS_已经完成了。
import Vue from 'vue'
import Vuex from 'vuex'
import db from '../firebase'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
todos: [],
newTodo: '',
errors: ''
},
mutations: { //syncronous, committed
GET_TODO: (state, todo) => {
state.newTodo = todo
},
ADD_TODO: state => {
db.collection('items').add({
title: state.newTodo,
created_at: Date.now(),
}).then(function(){
console.log('Document successfully added')
})
.catch((error) => {
this.errors = error
})
},
REMOVE_TODO: (state, id) => {
if (id) {
db.collection("items").doc(id).delete().then(function() {
console.log('Document successfully deleted')
})
.catch((error) => {
this.errors = error
})
} else {
this.errors = 'Invalid ID'
}
},
CLEAR_TODO: state => {
state.newTodo = ''
},
SET_TODO: state => {
let todos = []
db.collection('items').orderBy('created_at').onSnapshot((snapshot) => {
todos = []
snapshot.forEach((doc) => {
todos.push({ id: doc.id, title: doc.data().title })
})
state.todos = todos
})
}
},
actions: { //asyncronous, dispatched
getTodo: (context, todo) => {
context.commit('GET_TODO', todo)
},
addTodo: context => {
context.commit('ADD_TODO')
},
removeTodo: (context, id) => {
context.commit('REMOVE_TODO', id)
},
clearTodo: context => {
context.commit('CLEAR_TODO')
},
setTodo: context => {
context.commit('SET_TODO')
}
},
getters: {
newTodo: state => state.newTodo,
getTodos: state => {
return state.todos
}
}
})