簡體   English   中英

Vuex 更新時 Vue 組件不響應

[英]Vue Component Not Reacting When Vuex Updates

我正在開發一個允許貨運站管理訂單的系統。 我有初始更改和許多功能。 但是,即使我可以確認數據正在更新,我也無法讓一個組件更新另一個組件。

現在放一些代碼

./store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
 state: {
   greenboard :{
     station: 1,
     incomplete_orders:[],
     complete_orders:[],
   },
   yellowboard:{
     incomplete_orders:[],
     complete_orders:[],
   },
   dashboard:{

   },
 },
 getters: {
   greenIncomplete: state => {
     return state.greenboard.incomplete_orders;
   },

   greenComplete: state => {
     return state.greenboard.complete_orders;
   },

   greenStation: state => {
     return state.greenboard.station;
   }
 },
 mutations: {
   updateGreenOrders (state,payload){
     state.greenboard.incomplete_orders = payload.incomplete_orders;
     state.greenboard.complete_orders = payload.complete_orders;
   },
   updateGreenStation (state,payload){
     Vue.delete(state.greenboard, 'station');
     Vue.set(state.greenboard, 'station', payload.station);
     console.log(state.greenboard)
   }
 },
 actions: {}
});

/應用程序.js

/**
 * First we will load all of this project's JavaScript dependencies which
 * includes Vue and other libraries. It is a great starting point when
 * building robust, powerful web applications using Vue and Laravel.
 */

require('./bootstrap');

window.Vue = require('vue');


/**
 * The following block of code may be used to automatically register your
 * Vue components. It will recursively scan this directory for the Vue
 * components and automatically register them with their "basename".
 *
 * Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
 */

// const files = require.context('./', true, /\.vue$/i)
// files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))

Vue.component('example-component', require('./components/ExampleComponent.vue').default);
Vue.component('green-orders', require('./components/GreenOrders.vue').default);
Vue.component('stations-nav', require('./components/StationsNav.vue').default);
Vue.component('green-board', require('./components/GreenBoard.vue').default);
Vue.component('order-card', require('./components/OrderCard.vue').default);

/**
 * Next, we will create a fresh Vue application instance and attach it to
 * the page. Then, you may begin adding components to this application
 * or customize the JavaScript scaffolding to fit your unique needs.
 */
import store from "./store";
const app = new Vue({
    store,
    el: '#app',
});

站導航.vue

<template>
  <ul>
    <li v-for="station in stations" v-bind:key="station.id" v-on:click="stationChange(station.id)">{{station.station_name}}<br />{{station.description}}</li>
  </ul>
</template>

<script>
    export default {
      name:'StationsNav',
      components:{},
      data(){
          return {
            stations: [],
            chosen_station:0 ,
            error:"",
          }
      },
      created(){
        this.fetchStations();
      },

      methods:{
        async fetchStations(){
          try{
            const res = await axios.get('/internal/stations/');
            this.stations = res.data.data;
          }catch(e){
            console.log(e);
          }

        },

        stationChange(stationId){
          this.$emit("stationChange",{
            id:stationId
          });
        }
      },
      mounted() {

      }
    }
</script>

GreenOrders.vue

  <template>
    <div class="container-fluid">
      <div class="row justify-content-center">
        <div class="col-md">
          <h3>Green Orders</h3>
          <p>
            These orders are referenced from the Woocomerce system for orders that are ready to be shipped.
          </p>
          <order-card
          v-on:orderstatuschange = "changeOrderStatus"
          v-for="order in orders_incomplete"
          v-bind:key="order.id"
          v-bind:id="order.id"
          v-bind:order_id = "order.order_id"
          v-bind:number_of_items = "order.number_of_items"
          v-bind:completion = "order.completion"
          ></order-card>
        </div>
        <div class="col-md">
          <h4>Monitor Completed Orders</h4>
          <p>
            Completed orders eventually fall out of the system once their status is updated in Woocomerce
          </p>
          <order-card
          v-on:orderstatuschange = "changeOrderStatus"
          v-for="order in orders_complete"
          v-bind:key="order.id"
          v-bind:id="order.id"
          v-bind:order_id = "order.order_id"
          v-bind:number_of_items = "order.number_of_items"
          v-bind:completion = "order.completion"
          ></order-card>
        </div>
      </div>
      <div v-on:click="buttontest">
        BUTTON
      </div>
    </div>
  </template>

<script>
    export default {
      name:'OrdersDisplay',
      components:{},
      data(){
          return {
            orders_incomplete: [],
            orders_complete: [],
            error:"",
            station: this.$store.getters.greenStation
          }
        },

      created(){
        this.fetchIncomplete(this.station);
        this.fetchComplete(this.station);
      },

      methods:{
        async fetchIncomplete(station){
          try{
            const res = await axios.get('/internal/green-orders/'+station+'/0/');
            this.$store.commit({
              type:"updateGreenOrders",
              incomplete_orders: res.data.data,
            });
            this.orders_incomplete = this.$store.getters.greenIncomplete;
          }catch(e){
            console.log(e);
          }

        },
        async fetchComplete(station){
          try{
            const res = await axios.get('/internal/green-orders/'+station+'/1/');
            this.$store.commit({
              type:"updateGreenOrders",
              complete_orders: res.data.data,
            });
            this.orders_complete = this.$store.getters.greenComplete;
          }catch(e){
            console.log(e);
          }
        },

        async changeOrderStatus(order){
           try{
             const res = await axios.post('/internal/order/'+order.id+'/'+order.status+'/');
             this.orders_complete = res.data.data;
             this.fetchIncomplete(this.station);
             this.fetchComplete(this.station);
           }catch(e){
             console.log(e);
           }
        },

        buttontest(){
          console.log(this.$store.getters.greenStation); /*ATS:DEBUG REMOVE*/
          this.station = this.$store.getters.greenStation;
        }

      },

      mounted() {
      }
    }
</script>

綠板.vue

<template>
  <div class="container-fluid">
    <div class="row">
      <div class="col-3">
        <stations-nav v-on:stationChange="updateGreenStation"></stations-nav>
      </div>
      <div class="col-9">
        <green-orders></green-orders>
      </div>
    </div>
  </div>
</template>

<script>

    export default {
      name:'GreenBoard',
      components:{},
      data(){
          return {
            station: this.$store.getters.greenStation
          }
      },

      created(){

      },

      methods:{
        updateGreenStation(station){
          this.$store.commit({
            type:"updateGreenStation",
            station: station.id,
          });
          this.station = this.$store.getters.greenStation;
        }
      },
      mounted() {

      }
    }
</script>

這是呈現代碼的屏幕截圖在此處輸入圖像描述

當我單擊第二個站點更新 index.js 中的商店,然后單擊單詞按鈕時,它會執行 console.log 退出正確的站點。 但是,訂單不會根據存儲的站點進行更新,它只是繼續使用默認站點之一。 現在我可以設置那個按鈕來取消訂單,但我覺得我有點遺漏了一些東西,我是 VUE 的新手,但不是 javascript。我覺得這可能與觀察者或 Vuex 中的動作有關,但老實說我是有點不知所措。 先感謝您。

所以問題是缺乏對 Vuex 中動作如何工作的理解。 發生的事情是異步調用不會導致訂單重繪。 要執行異步操作,您需要在 Vuex 中使用操作。 這些允許調用 api 並等待該解決方案,然后通過作為 vuex 反應部分的突變將該信息提交給 state。 這也意味着我必須將我的大量本地數據更改為計算數據並返回存儲的內容,而不是使用 getter 來填充我的本地存儲。

這也讓我可以更新站點導航組件以正確使用 vuex 存儲。

下面我發布了現在按預期工作的更改文件。

/store/index.js


import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    greenboard :{
      station: 1,
      incomplete_orders:[],
      complete_orders:[],
    },
    yellowboard:{
      incomplete_orders:[],
      complete_orders:[],
    },
    dashboard:{

    },
  },
  getters: {
    greenIncomplete: state => {
      return state.greenboard.incomplete_orders;
    },

    greenComplete: state => {
      return state.greenboard.complete_orders;
    },

    greenStation: state => {
      return state.greenboard.station;
    }
  },
  mutations: {
    updateGreenOrders (state,payload){
      console.log(payload);
      state.greenboard.incomplete_orders = payload.incomplete_orders;
      state.greenboard.complete_orders = payload.complete_orders;
      state.greenboard.station = payload.station;
    },
    updateGreenStation (state,payload){
      Vue.delete(state.greenboard, 'station');
      Vue.set(state.greenboard, 'station', payload.station);
    }
  },
  actions: {
    async updateGreenOrders(context,payload){
      try{
        const incomplete = await axios.get('/internal/green-orders/'+payload.station+'/0/');
        const complete = await axios.get('/internal/green-orders/'+payload.station+'/1/');
        context.commit({
          type:"updateGreenOrders",
          incomplete_orders: incomplete.data.data,
          complete_orders:complete.data.data,
          station:payload.station
        });
      }catch(e){
        console.log(e);
      }
    }
  }
});

站導航.vue

<template>
  <ul>
    <li v-for="station in stations" v-bind:key="station.id" v-on:click="stationChange(station.id)">{{station.station_name}}<br />{{station.description}}</li>
  </ul>
</template>

<script>
    export default {
      name:'StationsNav',
      components:{},
      data(){
          return {
            stations: [],
            chosen_station:0 ,
            error:"",
          }
      },
      created(){
        this.fetchStations();
      },

      methods:{
        async fetchStations(){
          try{
            const res = await axios.get('/internal/stations/');
            this.stations = res.data.data;
          }catch(e){
            console.log(e);
          }

        },

        stationChange(stationId){
          this.$store.dispatch({
            type:"updateGreenOrders",
            station:stationId
          });
        }
      },
      mounted() {

      }
    }
</script>

GreenOrders.vue

  <template>
    <div class="container-fluid">
      <!--button class="buton" v-on:click="debug">
        debug
      </button-->
      <div class="row justify-content-center">
        <div class="col-md">
          <h3>Green Orders Station {{station}}</h3>
          <p>
            These orders are referenced from the Woocomerce system for orders that are ready to be shipped.
          </p>
          <order-card
          v-on:orderstatuschange = "changeOrderStatus"
          v-for="order in orders_incomplete"
          v-bind:key="order.id"
          v-bind:id="order.id"
          v-bind:order_id = "order.order_id"
          v-bind:number_of_items = "order.number_of_items"
          v-bind:completion = "order.completion"
          ></order-card>
        </div>
        <div class="col-md">
          <h4>Monitor Completed Orders</h4>
          <p>
            Completed orders eventually fall out of the system once their status is updated in Woocomerce
          </p>
          <order-card
          v-on:orderstatuschange = "changeOrderStatus"
          v-for="order in orders_complete"
          v-bind:key="order.id"
          v-bind:id="order.id"
          v-bind:order_id = "order.order_id"
          v-bind:number_of_items = "order.number_of_items"
          v-bind:completion = "order.completion"
          ></order-card>
        </div>
      </div>

    </div>
  </template>

<script>
    export default {
      name:'OrdersDisplay',
      components:{},
      data(){
          return {
            error:"",
          }
        },
      computed: {
        orders_incomplete(){
          return this.$store.state.greenboard.incomplete_orders;
        },
        orders_complete(){
          return this.$store.state.greenboard.complete_orders;
        },
        station(){
          return this.$store.state.greenboard.station;
        }
      },
      created(){
        this.fetchOrders(this.station);
      },

      methods:{
        fetchOrders(station){
          this.$store.dispatch({
            type:"updateGreenOrders",
            station:this.station
          });
        },

        async changeOrderStatus(order){
           try{
             const res = await axios.post('/internal/order/'+order.id+'/'+order.status+'/');
             this.fetchOrders(this.station);
           }catch(e){
             console.log(e);
           }
        },

        intervalUpdate(){
          var s = this;
          setInterval(function () {
            s.fetchOrders(s.station);
          }, 1000);
        },

        debug(){
          console.log("I'M THE CREAM OF THE CROP!")
        }

      },

      mounted() {
        //this.intervalUpdate();
        //this.fetchIncomplete(this.station);
        //this.fetchComplete(this.station);
        //console.log(this.$store.state.greenboard.incomplete_orders);
      }
    }
</script>

綠板.vue

<template>
  <div class="container-fluid">
    <div class="row">
      <div class="col-3">
        <!--stations-nav v-on:stationChange="updateGreenStation"></stations-nav-->
        <stations-nav></stations-nav>
      </div>
      <div class="col-9">
        <green-orders></green-orders>
      </div>
    </div>
  </div>
</template>

<script>

    export default {
      name:'GreenBoard',
      components:{},
      data(){
          return {
          }
      },

      created(){

      },

      methods:{

      },
      mounted() {

      }
    }
</script>

闡明問題的文檔: https://vuex.vuejs.org/guide/actions.html#dispatching-actions-in-components

結論

為了簡化問題,以便將來希望對其他人有所幫助。 如果你正在使用 Vuex,你需要使用 mutations 來響應。 如果某些東西是異步的,你需要使用一個動作,循環看起來像這樣。

dispatch action -> action resolves -> commit results -> vue reacts.

如果網站上任何其他更有經驗的人有其他意見,請告訴我。 謝謝 Decade Moon 的評論,讓我走上了這條路。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM