Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/456.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在Vuex中设置参数和参数_Javascript_Firebase_Vue.js_Google Cloud Firestore_Vuex - Fatal编程技术网

Javascript 如何在Vuex中设置参数和参数

Javascript 如何在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要求其第一个参数的

我正在使用Vue.js、Vuex和Firebase构建一个待办事项列表应用程序。应用程序似乎工作正常,商店文件成功地管理了从firestore到firestore的输入待办事项的检索和呈现。但是,我仍然对在Vuex中设置参数有疑问。see store.js中的REMOVE_TODO函数似乎需要两个参数,尽管id是函数实际代码中引用的唯一参数。换句话说,如果去掉初始参数,在本例中,state将返回一个错误,该错误为:Function CollectionReference.doc要求其第一个参数的类型为非空字符串,但它是:一个自定义对象。我的问题是:如果id参数是函数中实际使用的唯一参数,为什么这个REMOVE_TODO函数需要有两个参数才能正常工作?为什么需要另一个论点?下面是我的代码。谢谢

app.vue

<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
    }
  }
})