Vue.js:如何将特定对象中的布尔字段从 false 更改为 true @click 处于突变状态和带有动作 axios 的服务器?

Posted

技术标签:

【中文标题】Vue.js:如何将特定对象中的布尔字段从 false 更改为 true @click 处于突变状态和带有动作 axios 的服务器?【英文标题】:Vue.js: How to change booleanfield in specific object from false to true @click in state with mutations and server with actions axios? 【发布时间】:2020-07-26 02:32:41 【问题描述】:

当我执行 @click="updateTodoItem(todo.id, todo.title, todo.body) 时,我想将一个对象 (todo) 的布尔值从 false 更改为 true

这就是 1 个对象的外观:id: 1, title: "", body: "", done: false

更新(已完成): 我想通了并在这里更新了代码。我只能将 done 一个参数作为有效负载传递给存储操作。

首页.vue

<template>

<div class="container">

  <section class="hero is-link">
    <div class="hero-body">
      <div class="container">
        <h1 class="title">
          Hello Dudes
        </h1>
        <h2 class="subtitle">
          Hamster ToDo List
        </h2>
      </div>
    </div>
  </section>

<section class="section">

  <nav class="level">
    <div class="level-item has-text-centered">
      <div>
        <p class="heading">All Tasks</p>
        <p class="title">getTotalTodos</p>
      </div>
    </div>
    <div class="level-item has-text-centered">
      <div>
        <p class="heading">Tasks has to be done</p>
        <p class="title">getTodosFalse</p>
      </div>
    </div>
    <div class="level-item has-text-centered">
      <div>
        <p class="heading">Tasks finished</p>
        <p class="title">getTodosTrue</p>
      </div>
    </div>
    <!-- <div class="level-item has-text-centered">
      <div>
        <p class="heading">Likes</p>
        <p class="title">789</p>
      </div>
    </div> -->
  </nav>
</section>


<section class="section">
  <div class="columns">
    <div class="column is-half">
      <strong>Add ToDo</strong>
      <div class="control">
      <input class="input is-info" v-model="todoTitle" type="text" placeholder="Add Task Title">
      <input class="input is-info" v-model="todoBody" type="text" placeholder="Add Task Body">
      <button class="button is-link" @click="addTodoItem(title: todoTitle, body: todoBody, done: false); empyInput()">Add</button>
    </div>
    </div>
  </div>

  <div class="tabs is-small">
    <ul>
      <li class="is-active"><a>All Tasks </a></li> <span class="tag is-link">getTotalTodos</span>
      <li><a>Tasks still not done</a></li><span class="tag is-link">getTodosFalse</span>
      <li><a>Finished Tasks</a></li><span class="tag is-link">getTodosTrue</span>
      <!-- <li><a>Documents</a></li> -->
    </ul>
  </div>

  <article class="media" v-for="todo in todoItems" :key="todo.id">
    <figure class="media-left">
      <!-- <p class="image is-64x64">
        <img src="https://bulma.io/images/placeholders/128x128.png">
      </p> -->
    </figure>
    <div class="media-content">
      <div class="content">
        <p>
          <strong>todo.title</strong>  
          <br>
            todo.body
        </p>
      </div>
      <nav class="level is-mobile">
        <div class="level-left">
          <a class="level-item">
            <span class="icon is-small"><i class="fas fa-edit"></i></span>
          </a>
          <a class="level-item" v-if="todo.done==false" @click="updateTodoToTrue(todo.id)">
            <span class="icon is-small"><i class="fas fa-check"></i></span>
          </a>
          <a class="level-item" v-if="todo.done==true" @click="updateTodoToFalse(todo.id)">
            <span class="icon is-small"><i class="fas fa-undo"></i></span>
          </a>

          <a class="level-item" @click="deleteTodoItem(todo.id)">
            <span class="icon is-small"><i class="fas fa-trash"></i></span>
          </a>
        </div>
      </nav>
    </div>
    <div class="media-right">
      <button class="delete" @click="deleteTodoItem(todo.id)"></button>
    </div>
  </article>


</section>

</div>


</template>


<script>
// @ is an alias to /src
import mapGetters from 'vuex';
import mapActions from 'vuex';

export default 
  name: 'Home',
  data() 
    return
      todoTitle: '',
      todoBody: '',
    
  ,
  // updated() 
  //   this.$store.dispatch('getTodoItems');
  // ,
  computed: 
   ...mapGetters(['todoItems', 'getTotalTodos', 'getTodosTrue', 'getTodosFalse']) 
  ,
  methods: 
    ...mapActions(['addTodoItem', 'deleteTodoItem', 'updateTodoToTrue', 'updateTodoToFalse']),
    // addTodo() 
    //   return this.$store.actions.addTodoItem;
    empyInput() 
      this.todoTitle = '';
      this.todoBody = ''; 
    
  

</script>

商店

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios';

Vue.use(Vuex)

export default new Vuex.Store(
  state: 
    todoItems: []
  ,


  // Keep in mind that response is an HTTP response
  // returned by the Promise.
  // The mutations are in charge of updating the client state.
  mutations: 
    UPDATE_TODO_ITEMS (state, payload) 
      state.todoItems = payload;
    ,
    ADD_TODO_ITEMS (state, payload) 
      state.todoItems.push(payload)
    ,
    DELETE_TODO_ITEMS (state, payload) 
      state.todoItems.splice(payload, 1)
    ,
    changeTodoStatus: (state, payload) => 
      let index = state.todoItems.findIndex(el => 
        return el.id == payload.id
      )
      state.todoItems[index].done = payload.done
    

  ,

  actions: 
    getTodoItems ( commit ) 
      axios.get('http://127.0.0.1:8000/api/').then((response) => 
        commit('UPDATE_TODO_ITEMS', response.data)
      );
    ,
    addTodoItem ( commit , todoItem) 
      axios.post('http://127.0.0.1:8000/api/', todoItem).then((response) => 
        commit('ADD_TODO_ITEMS', response.data)
      );
    ,
    deleteTodoItem ( commit , todoItemId) 
      axios.delete('http://127.0.0.1:8000/api/' + todoItemId + '/').then((response) => 
        commit('DELETE_TODO_ITEMS', response.data)
      );
    , 
    updateTodoToTrue ( commit , todoItemId) 
      var payload = 
        done: true
      ;
      axios.patch('http://127.0.0.1:8000/api/' + todoItemId + '/', payload).then((response) => 
        commit('changeTodoStatus', response.data)
      );
    ,   
    updateTodoToFalse ( commit , todoItemId) 
      var payload = 
        done: false
      ;
      axios.patch('http://127.0.0.1:8000/api/' + todoItemId + '/', payload).then((response) => 
        commit('changeTodoStatus', response.data)
      );
    ,   
  ,

  getters: 
    todoItems: state => state.todoItems,
    getTotalTodos: state => state.todoItems.length,
    getTodosTrue: state => state.todoItems.filter(todo => todo.done).length,
    getTodosFalse: state => state.todoItems.filter(todo => !todo.done).length
  ,

  modules: 
  
)

【问题讨论】:

【参考方案1】:

我的问题是我试图将 3 个参数传递给商店中的操作有效负载。该操作仅接受 1 个参数,即有效负载。我将 axios 方法从 PUT 更改为 PATCH。

主页.vue

<template>

<div class="container">

  <section class="hero is-link">
    <div class="hero-body">
      <div class="container">
        <h1 class="title">
          Hello Dudes
        </h1>
        <h2 class="subtitle">
          Hamster ToDo List
        </h2>
      </div>
    </div>
  </section>

<section class="section">

  <nav class="level">
    <div class="level-item has-text-centered">
      <div>
        <p class="heading">All Tasks</p>
        <p class="title">getTotalTodos</p>
      </div>
    </div>
    <div class="level-item has-text-centered">
      <div>
        <p class="heading">Tasks has to be done</p>
        <p class="title">getTodosFalse</p>
      </div>
    </div>
    <div class="level-item has-text-centered">
      <div>
        <p class="heading">Tasks finished</p>
        <p class="title">getTodosTrue</p>
      </div>
    </div>
    <!-- <div class="level-item has-text-centered">
      <div>
        <p class="heading">Likes</p>
        <p class="title">789</p>
      </div>
    </div> -->
  </nav>
</section>


<section class="section">
  <div class="columns">
    <div class="column is-half">
      <strong>Add ToDo</strong>
      <div class="control">
      <input class="input is-info" v-model="todoTitle" type="text" placeholder="Add Task Title">
      <input class="input is-info" v-model="todoBody" type="text" placeholder="Add Task Body">
      <button class="button is-link" @click="addTodoItem(title: todoTitle, body: todoBody, done: false); empyInput()">Add</button>
    </div>
    </div>
  </div>

  <div class="tabs is-small">
    <ul>
      <li class="is-active"><a>All Tasks </a></li> <span class="tag is-link">getTotalTodos</span>
      <li><a>Tasks still not done</a></li><span class="tag is-link">getTodosFalse</span>
      <li><a>Finished Tasks</a></li><span class="tag is-link">getTodosTrue</span>
      <!-- <li><a>Documents</a></li> -->
    </ul>
  </div>

  <article class="media" v-for="todo in todoItems" :key="todo.id">
    <figure class="media-left">
      <!-- <p class="image is-64x64">
        <img src="https://bulma.io/images/placeholders/128x128.png">
      </p> -->
    </figure>
    <div class="media-content">
      <div class="content">
        <p>
          <strong>todo.title</strong>  
          <br>
            todo.body
        </p>
      </div>
      <nav class="level is-mobile">
        <div class="level-left">
          <a class="level-item">
            <span class="icon is-small"><i class="fas fa-edit"></i></span>
          </a>
          <a class="level-item" v-if="todo.done==false" @click="updateTodoToTrue(todo.id)">
            <span class="icon is-small"><i class="fas fa-check"></i></span>
          </a>
          <a class="level-item" v-if="todo.done==true" @click="updateTodoToFalse(todo.id)">
            <span class="icon is-small"><i class="fas fa-undo"></i></span>
          </a>

          <a class="level-item" @click="deleteTodoItem(todo.id)">
            <span class="icon is-small"><i class="fas fa-trash"></i></span>
          </a>
        </div>
      </nav>
    </div>
    <div class="media-right">
      <button class="delete" @click="deleteTodoItem(todo.id)"></button>
    </div>
  </article>


</section>

</div>


</template>


<script>
// @ is an alias to /src
import mapGetters from 'vuex';
import mapActions from 'vuex';

export default 
  name: 'Home',
  data() 
    return
      todoTitle: '',
      todoBody: '',
    
  ,
  // updated() 
  //   this.$store.dispatch('getTodoItems');
  // ,
  computed: 
   ...mapGetters(['todoItems', 'getTotalTodos', 'getTodosTrue', 'getTodosFalse']) 
  ,
  methods: 
    ...mapActions(['addTodoItem', 'deleteTodoItem', 'updateTodoToTrue', 'updateTodoToFalse']),
    // addTodo() 
    //   return this.$store.actions.addTodoItem;
    empyInput() 
      this.todoTitle = '';
      this.todoBody = ''; 
    
  

</script>

商店

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios';

Vue.use(Vuex)

export default new Vuex.Store(
  state: 
    todoItems: []
  ,


  // Keep in mind that response is an HTTP response
  // returned by the Promise.
  // The mutations are in charge of updating the client state.
  mutations: 
    UPDATE_TODO_ITEMS (state, payload) 
      state.todoItems = payload;
    ,
    ADD_TODO_ITEMS (state, payload) 
      state.todoItems.push(payload)
    ,
    DELETE_TODO_ITEMS (state, payload) 
      state.todoItems.splice(payload, 1)
    ,
    changeTodoStatus: (state, payload) => 
      let index = state.todoItems.findIndex(el => 
        return el.id == payload.id
      )
      state.todoItems[index].done = payload.done
    

  ,

  actions: 
    getTodoItems ( commit ) 
      axios.get('http://127.0.0.1:8000/api/').then((response) => 
        commit('UPDATE_TODO_ITEMS', response.data)
      );
    ,
    addTodoItem ( commit , todoItem) 
      axios.post('http://127.0.0.1:8000/api/', todoItem).then((response) => 
        commit('ADD_TODO_ITEMS', response.data)
      );
    ,
    deleteTodoItem ( commit , todoItemId) 
      axios.delete('http://127.0.0.1:8000/api/' + todoItemId + '/').then((response) => 
        commit('DELETE_TODO_ITEMS', response.data)
      );
    , 
    updateTodoToTrue ( commit , todoItemId) 
      var payload = 
        done: true
      ;
      axios.patch('http://127.0.0.1:8000/api/' + todoItemId + '/', payload).then((response) => 
        commit('changeTodoStatus', response.data)
      );
    ,   
    updateTodoToFalse ( commit , todoItemId) 
      var payload = 
        done: false
      ;
      axios.patch('http://127.0.0.1:8000/api/' + todoItemId + '/', payload).then((response) => 
        commit('changeTodoStatus', response.data)
      );
    ,   
  ,

  getters: 
    todoItems: state => state.todoItems,
    getTotalTodos: state => state.todoItems.length,
    getTodosTrue: state => state.todoItems.filter(todo => todo.done).length,
    getTodosFalse: state => state.todoItems.filter(todo => !todo.done).length
  ,

  modules: 
  
)

【讨论】:

以上是关于Vue.js:如何将特定对象中的布尔字段从 false 更改为 true @click 处于突变状态和带有动作 axios 的服务器?的主要内容,如果未能解决你的问题,请参考以下文章

如何从对象数组中获取特定数据并存储在js(vue js)中的新数组中

Vue.js - 如何按特定属性对数组中的对象进行排序并使用“v-for”进行渲染

Vue.JS 从 JSON 对象打印空值

如何正确地将数据从 vue 组件发布到 laravel 控制器

如何从视图中的上下文对象中检索对象或特定字段?

vue.js:如何从数组中的对象进行计算?